Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Reading and writing QObjects to/from XML
Forum Update on Monday, May 27th 2025

Reading and writing QObjects to/from XML

Scheduled Pinned Locked Moved General and Desktop
6 Posts 3 Posters 2.9k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    steve61
    wrote on last edited by
    #1

    I'm new to QT and, as an exercise to familiarize my way around Qt's meta objects, I thought I'd try to write a class to read and write QObject to/from XML files.

    What I'd like is to pass an object to a function and have that object written to an XML file, along with any child objects (single or in lists). The same for reading the object back in.

    Something like:

    MyXMLSerializer::WriteToXML(QObject* myObject, QString filePath);
    MyXMLSerializer::ReadFromXML(QObject* myObject, QString filePath);

    Using Q_PROPERTIES/QMetaProperty in the objects and QXmlStreamReader and QXmlStreamWriter it's easy enough to read/write an object's basic properties (QString, int, double, etc.) to/from XML, but I'm stuck trying to figure out how to read/write child objects and or child collections of objects.

    Could anyone offer a suggestion no how to go about handling these child objects?

    TIA

    1 Reply Last reply
    0
    • Chris KawaC Offline
      Chris KawaC Offline
      Chris Kawa
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi, welcome to devnet.

      Sounds like you just need to call recursively your writing function. Something like this:
      @
      void MyXMLSerializer::WriteToXML(QObject* myObject, QString filePath) {
      QXmlStreamWriter writer;
      ... //open a file etc.
      writer.writeStartDocument();
      serializeObject(myObject, writer);
      writer.writeEndDocument();
      }

      void MyXMLSerializer::serializeObject(QObject* obj, QXMLStreamWriter& writer) {
      writer.writeStartElement(...);

      ... //write this object data

      writer.writeStartElement("children");
      auto children = obj-0>children();
      for(auto child : children)
      serializeObject(child, writer);
      writer.writeEndElement(); //children

      writer.writeEndElement();
      }
      @
      Similarly for reading.

      1 Reply Last reply
      0
      • IamSumitI Offline
        IamSumitI Offline
        IamSumit
        wrote on last edited by
        #3

        Hi.
        i am not cleard to your problem .
        can you show me some xml file contetnts for QObject that you want to read and write.

        Be Cute

        1 Reply Last reply
        0
        • S Offline
          S Offline
          steve61
          wrote on last edited by
          #4

          Hi Chris,

          Thanks for your welcome and your reply.

          I follow everything you wrote, but what I don't understand is how to detect that that a property of the object that is being written, is a list or collection rather than a primitive field.

          I don't think I made myself entirely clear in my original post. I'd like to write a function to handle writing any QObject (with Q_PROPERTIES) to XML, not just one specific type.

          For example:

          @class Child
          {
          Q_PROPERTY(QString childName READ name....)
          ...
          }

          class Parent
          {
          Q_PROPERTY(QString parentName READ name...)
          Q_PROPERTY(Child child READ child...)
          Q_PROPERTY(List<Child> children READ children...)
          ...
          }

          // Construct a parent and add some children.
          Parent *p = new Parent();
          p->setName("Name");
          p->setChild(new Child());
          p->children.Add(new Child());
          p->children.Add(new Child());
          p->children.Add(new Child());

          // Write the parent and all its children to XML.
          MyXMLSerializer::WriteToXML(p, xmlFilePath);@

          The code writing the XML just gets a pointer to QObject and knows nothing of the object structure to be written other than what can be gleaned from meta data. Here's how I thought I'd handle it.

          @
          void MyXMLSerializer::serializeObject(QObject* obj, QXMLStreamWriter& writer) {
          // Iterate the meta data for the object's properties.
          int count = obj->metaObject()->propertyCount();
          for (int i = 0; i < count; i++){
          //Fetch the property meta data
          QMetaProperty metaproperty = obj->metaObject()->property(i);
          QString propertyName = metaproperty.name();

              // Write the property to XML - Fine for 
              // strings, ints, etc, but how to handle other 
              // QObjects or object lists?
              QString data = obj->property( propertyName.toUtf8()).toString();
              xml.writeTextElement(propertyName, data);
          }
          

          }
          @

          I could test each property's type in the loop (QMetaProperty::type()), but I'm not sure how to detect child objects or lists for special handling.

          I hope that makes sense.

          1 Reply Last reply
          0
          • Chris KawaC Offline
            Chris KawaC Offline
            Chris Kawa
            Lifetime Qt Champion
            wrote on last edited by
            #5

            [quote author="steve61" date="1415099334"] @
            // Construct a parent and add some children.
            Parent *p = new Parent();
            p->setName("Name");
            p->setChild(new Child());
            p->children.Add(new Child());
            p->children.Add(new Child());
            p->children.Add(new Child());
            @

            [/quote]

            That's not how you set a parent-child relation with QObjects. Should be:
            @
            Parent *p = new Parent();

            //pass a parent in the constructor
            new Child(p);

            //or set a parent later
            auto child = new Child();
            child->setParent(p);

            // this will get a read-only list of the children, you can't append to it
            auto children = p->children();
            @
            Having that you can get the list of children like I showed you.

            [quote author="steve61" date="1415099334"]I could test each property’s type in the loop (QMetaProperty::type()), but I’m not sure how to detect child objects or lists for special handling. [/quote]
            Ok, don't confuse "properties" and "child objects". These are two different things. For children I gave you the solution in the previous post.

            As for properties you can't simply convert a property to string like you did. Some types are not convertible like that eg. pointer will convert to a string because it's just a number (an address in memory) but it's useless.

            You can do something like this:
            @
            auto cnt = obj->metaObject()->propertyCount();
            for(int i = 0; i < cnt; ++i) {
            auto metaProp = obj->metaObject()->property(i);
            auto propName = metaProp.name();
            auto prop = metaProp.read(obj);
            QString data;
            switch(metaProp.type()) {
            //try to convert QVariant to string by default:
            default: data = prop.toString(); break;
            //but handle other types explicitly:
            case QMetaType::QSize:
            data = QString::number(prop.toSize().width()) + ", "
            + QString::number(prop.toSize().height());
            break;
            //and so on
            case ...
            }
            xml.writeTextElement(propertyName, data);
            }
            @

            Notice that you will have to handle all the "unusual" types yourself, because there' s no way to automatically convert "anything" to sensible string representation in a generic way. We're not in Java world ;)

            1 Reply Last reply
            0
            • S Offline
              S Offline
              steve61
              wrote on last edited by
              #6

              All understood Chris.
              Thanks for your help.

              1 Reply Last reply
              0

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved