XML DOM empty



  • Hi all,
    it must be a stupid error but I cannot see it:

    @
    QDomDocument xmlDocument;
    QDomProcessingInstruction procInstr = xmlDocument.createProcessingInstruction( "xml",
    "version='1.0' encoding='UTF-8'");
    xmlDocument.appendChild( procInstr );
    QDomElement rolesElement = xmlDocument.createElement( Role::XML_TAG_ROLES );
    xmlDocument.appendChild( rolesElement );

    QList<Role>::const_iterator roleIterator;
    for( roleIterator = roles.constBegin(); roleIterator != roles.constEnd(); roleIterator++ ){
    const Role& currentRole = *roleIterator;
    QDomElement currentRoleElement = xmlDocument.createElement( Role::XML_TAG_ROLE );
    rolesElement.appendChild( currentRoleElement );
    QDomElement roleIDElement = xmlDocument.createElement( Role::XML_TAG_ROLEID );
    QDomText roleIDText = xmlDocument.createTextNode( currentRole.id() );
    roleIDElement.appendChild( roleIDText );
    currentRoleElement.appendChild( roleIDElement );
    }
    @

    The above XML should create a dump of a custom object Role, and the iteration is working fine, but the end result is an empty XML document with only the processing instruction. It seems to me that all elements are parented right, but I guess it is not. Any suggestion?



  • I must be doing something wrong with the parenting of elements, since it seem that only the first element I add to the document is always printed. I've tied to remove the processing instruction and then the rolesElement is placed and so on. But I cannot see where the error is....



  • You're trying to put multiple elements on the level of the root node.

    • Create your processing instruction and add it to the document (like you're doing already).
    • Create a root element and add it to the document

    All further elements must be added not to the document, but to the root element (or below). You can retrieve the root element (the one you've created previously) via xmlDocument.documentElement().

    i.e you're trying this:
    @<?xml version="1.0" encoding="UTF-8"?>
    <element1>
    <element2>@
    when you should do:
    @<?xml version="1.0" encoding="UTF-8"?>
    <myRootElement>
    <element1>
    <element2>
    </myRootElement>@



  • [quote author="DerManu" date="1336494342"]

    All further elements must be added not to the document, but to the root element (or below). You can retrieve the root element (the one you've created previously) via xmlDocument.documentElement().

    [/quote]

    Uhm..sorry, I still don't get it. I've rewritten the code in order to make it clear what is the root element and I've removed the processing instruction since at the moment I don't need it:

    @QDomElement rootElement = xmlDocument.createElement( Role::XML_TAG_ROLES );
    rootElement.setAttribute( "count", roles.size() );

    // iterate on each role
    QList<Role>::const_iterator roleIterator;
    for( roleIterator = roles.constBegin(); roleIterator != roles.constEnd(); roleIterator++ ){
    const Role& currentRole = *roleIterator;

    QDomElement currentRoleElement = xmlDocument.createElement( Role::XML_TAG_ROLE );
    QDomElement roleIDElement = xmlDocument.createElement( Role::XML_TAG_ROLEID );
    QDomText roleIDText       = xmlDocument.createTextNode( currentRole.id() );
    roleIDElement.appendChild( roleIDText );
    currentRoleElement.appendChild( roleIDElement );
    rootElement.appendChild( currentRoleElement );
    

    }

    xmlDocument.appendChild( rootElement );@

    So each child element "currentRoleElement" is actually appended to the root element and the latter to the document. I don't see where I'm trying to add all elements as root elements of the document.
    The hierarchy should be that:

    @rootElement
    currentRoleElement
    roleIDElement
    roleIDText@



  • Sorry, it seems I've overlooked something in your code, I thought you were adding more than one element directly to the document instead of the root node.

    However, this works for me:
    @ QDomDocument xmlDocument;
    QDomElement rootElement = xmlDocument.createElement("root");
    rootElement.setAttribute( "count", 5 );
    QDomElement currentRoleElement = xmlDocument.createElement("subelement");
    QDomElement roleIDElement = xmlDocument.createElement("subelement");
    QDomText roleIDText = xmlDocument.createTextNode("subelement");
    roleIDElement.appendChild( roleIDText );
    currentRoleElement.appendChild( roleIDElement );
    rootElement.appendChild( currentRoleElement );
    xmlDocument.appendChild( rootElement );
    QFile file("./test.xml");
    file.open(QFile::WriteOnly|QFile::Truncate);
    QTextStream stream(&file);
    xmlDocument.save(stream, 2);@

    it produces as expected
    @<root count="5">
    <subelement>
    <subelement>subelement</subelement>
    </subelement>
    </root>@

    So my guess is there's something wrong with your "Role" mechanism.



  • I found a possible problem when creating the text node, that seem to break the tree.
    If I do the following:
    @QDomText roleIDText = xmlDocument.createTextNode( currentRole.id() );@
    no node is created at all.
    If I do for instance
    @QDomText roleIDText = xmlDocument.createTextNode( "Hello" + currentRole.id() );@
    the node is created with both the string "Hello" concat with the id() result.
    If I do:
    @QDomText roleIDText = xmlDocument.createTextNode( "" + currentRole.id() );@
    nothing is printed out.
    The id member function is defined as follows:
    @const QString& id() const;@
    Any idea?



  • An other update, that solves my problem but leaves me with a doubt.
    The following is the way I was testing the output document, thru which I report the above problems:

    @qdebug() << "XML Document " << xmlDocument.toString( 5 );@

    and the following is a way that prints out the document into a file that works:

    @
    QFile file( "/home/luca/tmp/roles.xml");
    file.open(QFile::WriteOnly|QFile::Truncate);
    QTextStream stream( &file );
    xmlDocument.save( stream, 2);
    @

    So seems to me that the document is suffering some way of "flushing" when the toString is called?



  • That sure is a bit strange. I'm not aware of such buffering making toString and save behave differently, and it doesn't happen when I test it.

    What does currentRole.id() typically contain? Invalid tag characters? Numbers only? In this case, the XML becomes invalid, so when your InvalidDataPolicy (see QDomImplementation::setInvalidDataPolicy) is DropInvalidCharacters or ReturnNullNode, you might get an empty XML document. However, this would cause some debug output along the lines of "Calling appendChild() on a null node does nothing."



  • [quote author="DerManu" date="1336653888"]T
    What does currentRole.id() typically contain? Invalid tag characters? [/quote]

    Plain text, no makrup signs (e.g., dev, doc). I'm investigating more to see if I find the cause.



  • I've just looked through the code of "qdom.cpp":http://qt.gitorious.org/qt/qt/blobs/4.8/src/xml/dom/qdom.cpp and there are no signs of such buffering. Both QDomDocument::save and toString internally call the save functions recursively on the document nodes. In fact, toString just creates a QTextStream on the returned string and writes its content with save itself. So this definetly isn't the cause.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.