Results 1 to 16 of 16

Thread: Best way of creating an XML node from an object

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Best way of creating an XML node from an object

    I want my application to be able to save some of it's objects to an XML file. I have written the code below, but i'm not sure if this is the best way to do it. Surely working with XML should be simpler.
    By that i mean that the code i have is very repetitive as i have to create each node as well as the inner text node. Are there helper functions to simplify adding basic elements like this?

    Qt Code:
    1. // Creates and returns an XML node that represents SomeObject
    2. QDomElement SomeObject::asXmlNode(QDomDocument& doc) {
    3. QDomElement tempNode;
    4. QDomElement root = doc.createElement("someobject");
    5.  
    6. tempNode = doc.createElement("variable1");
    7. tempNode.appendChild(doc.createTextNode(variable1));
    8. root.appendChild(tempNode);
    9.  
    10. tempNode = doc.createElement("variable2");
    11. tempNode.appendChild(doc.createTextNode(variable2));
    12. root.appendChild(tempNode);
    13.  
    14. tempNode = doc.createElement("rectangle");
    15. tempNode .setAttribute("x", getDimensions().x());
    16. tempNode .setAttribute("y", getDimensions().y());
    17. tempNode .setAttribute("width", getDimensions().width());
    18. tempNode .setAttribute("height", getDimensions().height());
    19. root.appendChild(tempNode);
    20.  
    21. // ... etc
    22.  
    23. return root;
    24. }
    25.  
    26. // And elsewhere, write the xml node to a file
    27. QDomDocument xmlDoc;
    28. xmlDoc.appendChild(object->asXmlNode(xmlDoc));
    29.  
    30. QTextStream stream(&file);
    31. stream << xmlDoc.toString(4);
    To copy to clipboard, switch view to plain text mode 
    Last edited by xtal256; 6th April 2011 at 00:05. Reason: updated contents
    [Window Detective] - Windows UI spy utility
    [War Thunder]

  2. #2
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Best way of creating an XML node from an object

    You could look at QXmlStreamWriter and QXmlStreamReader.

  3. #3
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Best way of creating an XML node from an object

    I wasn't sure if it was good practice to use those classes, or if i should be working with XML objects. I guess i was a bit confused since there are a number of different ways of writing XML (there is also QDomNode::save). Besides, the need to writeStartElement, writeWhateverElse, then writeEndElement is just as tedious as how i'm currently doing it.
    [Window Detective] - Windows UI spy utility
    [War Thunder]

  4. #4
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Best way of creating an XML node from an object

    There is no magic serialiseMyDataAsXML() method. Ultimately you have no choice but to write code to output the things that need to be saved (and matching read code). With the streams approach you can put suitable stream operators into classes that need to be serialised so that they can serialise/deserialise themselves (keeping the routines small). This is of benefit with complex structures of objects: you don't end up with a single must-see-and-know-everything method.

    If all the items to be saved/restored are exposed as QObject properties then you might be able to use some Qt Meta Object trickery to produce a generic save/load routine.

    You can also look at Boost serialization for other inspiration. I find it clever but tedious in different ways.

  5. #5
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Best way of creating an XML node from an object

    With the streams approach you can put suitable stream operators into classes that need to be serialised so that they can serialise/deserialise themselves (keeping the routines small). This is of benefit with complex structures of objects: you don't end up with a single must-see-and-know-everything method.
    Yeah, but i can do (and am doing) the same thing with my asXmlNode method. For example:
    Qt Code:
    1. QDomElement SomeObject::asXmlNode(QDomDocument& doc) {
    2. QDomElement tempNode;
    3. QDomElement root = doc.createElement("someobject");
    4.  
    5. tempNode = doc.createElement("variable1");
    6. tempNode.appendChild(this->variable1->asXmlNode());
    7. root.appendChild(tempNode);
    8.  
    9. return root;
    10. }
    To copy to clipboard, switch view to plain text mode 
    [Window Detective] - Windows UI spy utility
    [War Thunder]

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Best way of creating an XML node from an object

    True but here you assume the data is attached to the root node of the document. Suppose you want to serialize a list of such objects - then you'd want the object representation to be attached to the list node and not to the root node.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  7. #7
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Question Re: Best way of creating an XML node from an object

    Hi again.

    I have implemented a solution using a DOM structure as i described above (the asXmlNode methods). But now i am thinking QXmlStreamWriter might be better. I just have one problem though; it's going to be hard to do it with class inheritance.

    Currently i have the following class hierarchy, where each object would have a method to write itself on the XML stream.
    Qt Code:
    1. class ObjectA {
    2. // blah blah
    3.  
    4. virtual void toXmlStream(QXmlStreamWriter& stream);
    5. };
    6.  
    7. class ObjectB : public ObjectA {
    8. // blah blah
    9.  
    10. void toXmlStream(QXmlStreamWriter& stream);
    11. };
    To copy to clipboard, switch view to plain text mode 

    ObjectA would write it's element and child elements like so:
    Qt Code:
    1. void ObjectA::toXmlStream(QXmlStreamWriter& stream) {
    2. stream.writeStartElement("ObjectA");
    3.  
    4. stream.writeStartElement("variable1");
    5. stream.writeTextElement(variable1);
    6. stream.writeEndElement();
    7.  
    8. // more child elements ...
    9.  
    10. stream.writeEndElement(); // end of "ObjectA" element
    11. }
    12.  
    13. // And elsewhere, write the xml to a file
    14. QXmlStreamWriter stream(&file);
    15. stream.writeStartDocument();
    16. object->toXmlStream(stream);
    17. stream.writeEndDocument();
    To copy to clipboard, switch view to plain text mode 

    But then what happens when ObjectB overrides that method with the intent of extending it:
    Qt Code:
    1. void ObjectB::toXmlStream(QXmlStreamWriter& stream) {
    2. ObjectA::toXmlStream(stream);
    3. // Oops, super class has just written the end of it's main element...
    4. // the elements below will be orphaned
    5.  
    6. stream.writeStartElement("variable2");
    7. stream.writeTextElement(variable2);
    8. stream.writeEndElement();
    9.  
    10. // more of ObjectB's child elements ...
    11. }
    To copy to clipboard, switch view to plain text mode 

    The solution is to write the objects "main" element before the object's toXmlStream method is called:
    Qt Code:
    1. QXmlStreamWriter stream(&file);
    2. stream.writeStartDocument();
    3. stream.writeStartElement("ObjectA");
    4. objectB->toXmlStream(stream);
    5. stream.writeEndElement();
    6. stream.writeEndDocument();
    To copy to clipboard, switch view to plain text mode 
    And ObjectA::toXmlStream would not write it's own "ObjectA" element.

    But this just seems ugly. It would mean that the method writing the object would need to know something about that object. And i would have to ensure i consistently write the same element where ever i write that object to the xml stream.

    Is this how it has to be? In which case, i will go back to using the DOM way. Or is there a neat/simple way around this problem.
    Last edited by xtal256; 19th April 2011 at 01:21.
    [Window Detective] - Windows UI spy utility
    [War Thunder]

  8. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Best way of creating an XML node from an object

    Why do you think you need to write the object tag before you call toXmlStream()?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  9. #9
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Best way of creating an XML node from an object

    I just explained why.

    If i called ObjectB::toXmlStream, wouldn't this be the output:
    Qt Code:
    1. <ObjectA>
    2. <variable1>value of variable1</variable1>
    3. ...
    4. </ObjectA>
    5. <variable2>value of variable2</variable2>
    To copy to clipboard, switch view to plain text mode 

    As the super method is called first, it writes both it's opening and ending tag. But the inherited class needs to write elements in there too.
    [Window Detective] - Windows UI spy utility
    [War Thunder]

  10. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Best way of creating an XML node from an object

    So why don't you split this single method into three methods (open tag, write contents, close tag) just like the stream writer does? Possibly even with a way to allow the parent class to append attributes to the opening tag created by the child class using writeAttributes. This should work:
    Qt Code:
    1. class Object {
    2. public:
    3. virtual void serialize(XmlStreamWriter &writer) {
    4. openTag(writer);
    5. writeContents(writer);
    6. closeTag(writer);
    7. }
    8. protected:
    9. virtual void openTag(XmlStreamWriter &writer, bool open = true) {}
    10. virtual void closeTag(XmlStreamWriter &writer) { writer.writeEndElement();}
    11. virtual void writeContents(XmlStreamWriter &writer) {}
    12. };
    13.  
    14. class SubObject : public Object {
    15. protected:
    16. virtual void openTag(XmlStreamWriter &writer, bool open = true) {
    17. if(open) { stream.writeStartElement(...); }
    18. writer.writeAttribute(...);
    19. Object::openTag(writer, false); // pass false to mark the parent should not open the tag by itself
    20. }
    21. virtual void closeTag(XmlStreamWriter &writer) {
    22. // this should work the other way round, the top-most class should close the tag
    23. writer....
    24. Object::closeTag(writer);
    25. }
    26. virtual void writeContents(XmlStreamWriter &writer) {
    27. Object::writeContents(writer);
    28. writer...
    29. }
    30. };
    To copy to clipboard, switch view to plain text mode 
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  11. #11
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Best way of creating an XML node from an object

    Yeah, i was thinking of that too. It would mean that serializable classes would need 3 such methods instead of just 1, but it seems like the only other way.
    Besides, my subclasses do not need specific element names or attributes, so i do not need to override the open and close tag methods for them.

    thanks for your help.
    [Window Detective] - Windows UI spy utility
    [War Thunder]

Similar Threads

  1. Replies: 21
    Last Post: 28th September 2010, 10:59
  2. Replies: 10
    Last Post: 17th September 2009, 20:12
  3. how to justfy a node is leaf node or not
    By weixj2003ld in forum Qt Programming
    Replies: 4
    Last Post: 9th April 2009, 07:40
  4. Creating a QAccessibleWidget object for widget
    By Rakesh_Kumar in forum Qt Programming
    Replies: 0
    Last Post: 27th January 2009, 08:13
  5. Creating object of other class in Run() method
    By santosh.kumar in forum Qt Programming
    Replies: 2
    Last Post: 15th May 2007, 15:05

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.