Results 1 to 16 of 16

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

  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 01: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 02: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]

  12. #12
    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

    Quote Originally Posted by xtal256 View Post
    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.
    They don't need it now but they might need it in two weeks or seven months from now (like if you need to introduce versioning). Better safe than sorry.

    If you want something simpler, you can always do this:
    Qt Code:
    1. class Object {
    2. public:
    3. void serialize(QXmlStreamWriter &writer) {
    4. writer.writeStartElement(name());
    5. writeContents(writer);
    6. writer.writeEndElement();
    7. }
    8. protected:
    9. virtual QString name() const { return "Object"; }
    10. virtual void writeContents(QXmlStreamWriter &writer) {}
    11. };
    12.  
    13. class SubObject : public Object {
    14. protected:
    15. QString name() const { return "SubObject"; }
    16. void writeContents(QXmlStreamWriter &writer) {
    17. Object::writeContents(writer);
    18. writer....
    19. }
    20. };
    To copy to clipboard, switch view to plain text mode 
    Last edited by wysota; 19th April 2011 at 02:45.
    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.


  13. #13
    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

    Quote Originally Posted by wysota View Post
    Quote Originally Posted by xtal256
    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.
    They don't need it now but they might need it in two weeks or seven months from now (like if you need to introduce versioning). Better safe than sorry.
    Yeah, but i can always add it then. It's just a matter of how much functionality i want right now. If i ever need to make subclasses use their own element name or add attributes, then i can quite simply override the open and close tag methods.
    [Window Detective] - Windows UI spy utility
    [War Thunder]

  14. #14
    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

    Quote Originally Posted by xtal256 View Post
    Yeah, but i can always add it then. It's just a matter of how much functionality i want right now. If i ever need to make subclasses use their own element name or add attributes, then i can quite simply override the open and close tag methods.
    I guess you're not used to working in a team... Happy you
    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.


  15. #15
    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

    Actually, that is probably what most teams would do
    Besides, this is a personal project i am working on, so i can do whatever i want.
    [Window Detective] - Windows UI spy utility
    [War Thunder]

  16. #16
    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

    Quote Originally Posted by xtal256 View Post
    Actually, that is probably what most teams would do
    Where I work I have to think two steps ahead. Since most of what I do there is meant to be ready for "two weeks ago", before even the code is stable it is already being used by others who sometimes abuse it and changing my API (or just the code logic) without breaking their code is hard, so I have to first think how they might abuse my code tomorrow and then how to make sure them doing that will not break the code I will be writing next week. I'd certainly go for three methods in this case if I had to do it the way you do it. Well... I wouldn't do it like that but that's another thing. I'd probably either subclass QXmlStreamWriter or write a set of overloaded standalone functions for serialization just like QDataStream does. Especially that with XML you can implement inheritance by using subnodes which is much more readable.

    xml Code:
    1. <SubObject>
    2. <parent>
    3. <Object>
    4. <!-- ... -->
    5. </Object>
    6. </parent>
    7. <attributes>
    8. <!-- ... -->
    9. </attributes>
    10. </SubObject>
    To copy to clipboard, switch view to plain text mode 

    On a side note, this is also how ECMAScript implements "inheritance" - by using prototypes.
    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.


Similar Threads

  1. Replies: 21
    Last Post: 28th September 2010, 11:59
  2. Replies: 10
    Last Post: 17th September 2009, 21: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, 08:40
  4. Creating a QAccessibleWidget object for widget
    By Rakesh_Kumar in forum Qt Programming
    Replies: 0
    Last Post: 27th January 2009, 09:13
  5. Creating object of other class in Run() method
    By santosh.kumar in forum Qt Programming
    Replies: 2
    Last Post: 15th May 2007, 16: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.