[SOLVED] Serialization of custom object to XML



  • Is there a mechanism which allows simple serialization to XML?
    I've been using QSettings for serialization of custom object after registering their type. However, it uses QDataStream which writes the output data in binary form. Let's assume that I have this class:

    @class test
    {

    public:
    test();

    int number;
    QString title;
    QColor color;
    };@

    And example of serialized object of the class:

    @<object>
    <number>0</number>
    <title>Some text</title>
    <color>blue</color>
    </object>@

    And to addition to that I would like to store a list of those objects, so at the end I would like to get something like that in XML:

    @
    <list>
    <object>
    <number>0</number>
    <title>Some text</title>
    <color>blue</color>
    </object>
    <object>
    <number>1</number>
    <title>Some other text</title>
    <color>green</color>
    </object>
    </list>@

    I have given a look at QJSON but this is not what I really want. Does there exist something like that or should I manually write some procedures to get it work the way I want it to?


  • Moderators

    The only automatic serialization you will get in Qt is using QDataStream. If you want other data type, you need to write the parser yourself.

    Please note, however, that QDataStream can be saved to a file, also to an XML file (the entries in the file will still be binary/ base64, of course).



  • Yes, QDataStream writes data in binary form. That is why I don't want to use it. The reason behind writing the data to XML is to have a configuration file which can be changed by hand in any editor. XML is the best option, I think.

    So, as far as I understand the only way is to do it manually, right? Isn't there even a partial API in Qt which can make the work a bit less cumbersome.


  • Moderators

    Correct, you are on your own. I suspect, however, that the Qt Project would be more than happy to see a contribution that would add QTextStream operators to various Qt classes. So maybe it is a good idea to consider modifying Qt itself here, instead of writing customs stringifiers in your code.

    Just got an idea. You can test using qDebug() with a custom message handler for this. QDebug is very clever about Qt classes, and can stringify a lot of them.



  • Hello,

    I think you are looking for for read/write XML files. I think you can use QDomDocument for this purpose. Check this code for reading XML files, the similar way you can do for writing.

    Code for Reading

    @int main(int argc, char *argv[])
    {
    QApplication app(argc, argv);

    QFile xmlFile&#40;":/sample.xml"&#41;;
    xmlFile.open(QIODevice::ReadOnly&#41;;
    
    QDomDocument doc;
    doc.setContent(xmlFile.readAll(&#41;&#41;;
    
    QDomElement root = doc.documentElement();
    QDomElement nodeTag = root.firstChildElement("device");
    while(!nodeTag.isNull())
    {
        qDebug()<<"attributes of device"<<nodeTag.attribute("desc")<<"type"    <<nodeTag.attribute("type") <<"id"<<nodeTag.attribute("id");
        nodeTag = nodeTag.nextSiblingElement("device");
    }
    

    QDomNodeList nodeList = root.elementsByTagName("function");

    for(int i =0;i<nodeList.count();i++)
    {
    QDomElement el = nodeList.at(i).toElement();

    qDebug()<<nodeList.at(i).toElement().text(); // prints content
    qDebug()<<el.attribute("id"); // prints id value
    

    }

    xmlFile.close();
    return app.exec&#40;&#41;;
    

    }@

    Regards
    Ansif

    Edit: I forgot to put the XML files.

    @<rootTag>
    <device desc="customDevice1" type="1" id="21"/>
    <device desc="customDevice2" type="2" id="22"/>
    <device desc="customDevice3" type="3" id="23"/>
    <function id="1">Some content function1</function>
    <function id="2">Some content function2</function>
    <function id="3">Some content function3</function>
    </rootTag>@

    Please check this link for more deatils:
    "Link1":http://stackoverflow.com/questions/12637858/update-xml-file-in-qt/12638898#12638898
    "Link2":https://qt-project.org/forums/viewthread/18842



  • Actually, QTextStream does what it does pretty well. However, there is still a debate about how to represent some Qt object like for example QColor. It can be represented by name, however. But there are others which wouldn't be very obvious considering the way how they should be handled. All in all, this is a good idea. I think I will do something like that for classes which I use.
    Still, as I said at the beginning, I would like to serialize and this gets more tricky.

    Edit:
    Ansif, I will give it a shoot. Along with combination of previous.

    Edit2:
    Is there a way to get access to desired node via path to it? Let's say I have pat:
    /general/dataSet/0/Name
    By invoking read on this path I would get the value of Name attribute. And vice versa by invoking write, it would write data to this attribute.
    It would be nice to actually have a smart write procedure.
    If the parent node doesn't exist it creates it. For example I have only node dataSet which lies in /general and it doesn't have any children. After invoking write on /general/dataSet/0/Name it creates nodes down to /general/dataSet/0 and at the end it creates an attribute named Name.
    What is more, it changes attributes into nodes at hand. Let's say when I invoke /general/dataSet/0/Name/First
    on /general/dataSet/0/Name where it was actually an attribute it changes it into a node.



  • Hi,

    Sorry for the late reply. Off course you can access any node from the XML file. I hope the below code will help you in some extent.

    @

    QDomDocument doc;

    // Read scheme file
    QFile file&#40;"Filename.xml"&#41;;
    if (!file.open(QIODevice::ReadOnly&#41;&#41;
        throw Exception;
    
    // Put file content to dom parser
    if (!doc.setContent(&file&#41;)
        throw Exception;
    

    QDomElement element = doc.documentElement();

    for (int i = 0; i < element.childNodes().count(); i++)
    {
    QDomElement node = element.childNodes().at(i).toElement();

        if (node.nodeName().toLower() == "node_parent")
        {
            for (int j = 0; j < node.childNodes().count(); j++)
            {
                if (node.childNodes().at(j).nodeName() == "node_child")
                    
            }
        }
    

    }
    @

    Regards
    Ansif



  • Here is another example on how to use "XML serialization":http://www.openshots.de/2011/03/qsettings-mit-xml-format/ with QSettings



  • Thank you all for the replies.
    I did something similar to the solution offered by andreyc. However, in my code I only use XML without QSettings. But the job is done and it works pretty well.



  • [quote author="Wojciech Domski" date="1407851630"]Thank you all for the replies.
    I did something similar to the solution offered by andreyc. However, in my code I only use XML without QSettings. But the job is done and it works pretty well. [/quote]

    Happy to hear the good news.



  • I have tried found to open the link: "http://www.openshots.de/2011/03/qsettings-mit-xml-format" wich told andreyc but that link is broken, is there some link where i can seet that example?
    Tkank you


Log in to reply
 

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