Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

I can't find a Qt class that provides an interface to update XML in a file



  • My use case is that I need to read an xml file to get a specific node, display the value to the user then write the updated value back to the xml file. I haven't found a Qt class that provides that functionality.

    For example, the following is a sample of a config from a camera device I'm working with:

    <?xml version="1.0"?>
    <puregevpersistencefile version="1.0">
      <device name="" version="1.0">
            <device>
              <parameter name="DeviceScanType">Linescan</parameter>
              <parameter name="SensorDigitizationTaps">One</parameter>
              <parameter name="Width">2048</parameter>
            </device>
      </device>
    </puregevpersistencefile>
    

    In one case, I want to get the "Width," display "2048" to the user and let them update it. I would then take what they specify, replace 2048 with their value and update the xml file which would then be uploaded to the device.

    QDomDocument is easy to read in the XML file. But, it doesn't provide an support to select a single node or update the text of the node. In my case, I can't search by "device" because the manufacturer decided to have a device node inside of another device node. I need an xpath to specify the node properly.

    QXmlQuery works great for supporting xpath search. I have that working. But, I don't see any way to update the xml.

    The QXmlStreamReader and QXmlSimpleReader are SAX parsers allowing the developer to write the code to understand where in the XML the parser is at. The problem is that each device has unique xml which makes for a lot of coding and I don't see a way to update the node value in the process.

    It looks like I may have to use an open source product like pugixml. Am I missing something? Is there a Qt class that has this functionality?


  • Lifetime Qt Champion



  • @Christian-Ehrlicher Thanks for the reply. I've read the documentation on that a number of times and haven't seen how to do what I'm trying to do.

    From the xml, you can see that elementsByTag name with "Device" passed in, will return a "node" device, then I'll have to get a child device for that with a tag of "device." This is specific to the xml and will be different for each xml file. The path may be different for any attribute. I have only shows a small sample of the xml file which is quite large and has many hierarchies.

    I was hoping to have a generic object that would work with any xml file in which I could pass an xPath string to specify the node and have it return the "value" of the entry.


  • Lifetime Qt Champion

    A short look for 'Qt xpath' will get you to https://doc.qt.io/qt-5/xquery-introduction.html


  • Lifetime Qt Champion

    @Christian-Ehrlicher

    Hi
    And unlike QXmlQuery,
    the Qt implementation of XQuery does allow to alter the data ?
    Its not really clear to me from the Docs.



  • I don't really understand what is going on here, what @Daniel-Williams is actually looking for?

    If it's searching a document, XQuery, XPath & QXmlQuery will do that, but not modify.

    If it's modifying a document, QDomDocument, or QXmlStreamWriter etc., but they're not clever at searching.

    QDomDocument is easy to read in the XML file. But, it doesn't provide an support to select a single node or update the text of the node

    Well, yes, it does provide ability to update. [And also to select node(s).] I agree the docs don't seem obvious, but I presume you either create a new node to replace the existing one, or doesn't https://doc.qt.io/qt-5/qdomnode.html#setNodeValue replace the text?


  • Lifetime Qt Champion

    Hi
    I think he wants to use searching versus traversing a DOM tree and then
    modify the XML once found.
    So If QDomDocument could accept xpath or similar to return active nodes
    from the tree i think that would be it.
    However, im not familiar enough with the Qt XML classes to know if it can be combined that way.



  • In Qt I believe it is the case that QDomDocument is good for altering but does not play well with XPath, that likes QXmlQuery, which doesn't update. A cleft stick. Read for example all of https://stackoverflow.com/questions/56062025/search-for-nodes-in-a-qdomdocument-using-xpath, or https://stackoverflow.com/questions/9804686/updating-a-xml-file-using-qt-dom. That's just how it is.

    If one wants to update my feeling is QDomDocument. Now, the question is, much as it would be desirable, does OP really need XPath/XQuery to locate the target nodes for his purposes? For many queries it is not too hard to do QDomDocument traversal, there are the "getElement" & "firstChild" type functions.



  • As others have covered, there are models for reading and parsing XML documents, but I believe they all expect the document to be fully read into memory. If true, then modifying an element would require reading the document into a suitable object, finding the element in question, modifying it, then traversing the tree and writing ALL its elements back to storage.

    I don't believe there is any edit-in-place facility for XML documents. You will need to rewrite the complete document by traversing its nodes and writing them out.

    All I've ever used is the QDom model so my knowledge of other mechanisms is limited. However, it should let you search for any element in question (even nested), if you know the tags.



  • @Kent-Dorfman

    I don't believe there is any edit-in-place facility for XML documents. You will need to rewrite the complete document by traversing its nodes and writing them out.

    QDomDocument does allow "edit-in-place", in the sense of in memory. https://forum.qt.io/topic/43724/solved-save-qdomdocument-to-xml gives sample code for (re-) writing the complete document (via QDomDocument.toString()) to file (without you having to write the code to traverse the tree).



  • Thank you for all the good discussion on this subject!

    I'm developing an application that will connect to several different types of image capture devices. Each device type uses xml to download/upload configuration data for the device.

    If updating the xml requires traversing the DOM object, then I'll have to have a unique object for each type. However, if I can use xpath to search the dom object to find the node to update, then I can have one general purpose object that will handle all the devices which will be much more flexible when adding new devices.

    Currently, I'm looking at Stanislaw Adaszewski's implementation of QDomNode to allow qxmlquery and qdomdocument work together:

    https://www.qtcentre.org/threads/37645-QAbstractXmlNodeModel-implementation-QDomNodeModel-QXmlQuery?p=220733#post220733
    https://adared.ch/qdomnodemodel-qxmlquery/

    I haven't tested it, yet, but it looks hopeful for what I'm trying to accomplish.



  • For anyone who might be following this path, here's what I've found.

    I tried pugixml. That is well-written and lightweight. However, my xml documents are too large / complicated. It worked well on smaller / less complicated xml documents, but didn't work as well on my document.

    I was able to get QDomNode from Stanislaw Adeszewski searching the dom working well. But, I was not able to get the QDomNode that is returned to actually update the underlying QDomDocument. It's great for adding xpath searching to QDomDocument.

    I wrote my own little xpath function to search QDomDocument and update it. It works well on simple xpath statements. But, in my heart I know I'll probably run into more complex xpath queries. I'm going to look at apache foundation open-source xerces tool.

    Here's a good page with info on xml c++ tools: https://www.ibm.com/developerworks/xml/library/x-ctlbx/index.html



  • @Daniel-Williams
    A useful post.

    However, I tried to help you earlier and I still don't know why you found it impossible. I do admit I have not tried this stuff(!) But...

    I was able to get QDomNode from Stanislaw Adeszewski searching the dom working well. But, I was not able to get the QDomNode that is returned to actually update the underlying QDomDocument.

    https://doc.qt.io/qt-5/qdomnode.html#details says:

    Nodes are inserted with insertBefore(), insertAfter() or appendChild(). You can replace one node with another using replaceChild() and remove a node with removeChild().

    That's inserting/replacing/updating nodes covered. findChild() etc. find QDomNodes in the document. And https://doc.qt.io/qt-5/qdomnode.html#setNodeValue covers replacing a text node's text.

    So not sure what did not work for you, I would have thought all of these will modify your QDomDocument, no?


Log in to reply