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. Appending to xml
Forum Updated to NodeBB v4.3 + New Features

Appending to xml

Scheduled Pinned Locked Moved Solved General and Desktop
21 Posts 4 Posters 8.6k Views 2 Watching
  • 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.
  • chawilaC Offline
    chawilaC Offline
    chawila
    wrote on last edited by chawila
    #1

    I have an xml file that was generated using c++.
    so i used it as a model in qml.
    now as the user is interacting with the App, i want to append to that xml in c++, then reload the xmlModel in qml.

    i tried these:

        QString filename= appFolder+"/db/"+xmlFile;
    
            if(append == true){
                qDebug() << "appending...";
                file.open(QIODevice::ReadWrite | QIODevice::Text);
                QDomDocument doc;
                doc.setContent(&file);
                QDomNode root = doc.firstChild();
                
            }else{
                qDebug() << "trancating and adding to file..";
                file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text);
                QDomDocument doc("Products");
                QDomElement root = doc.createElement("Products");
                doc.appendChild(root);
            }
    

    Then i have a loop that should iterate while appending to the roort variable.
    So if i try to access the variable doc so that i can add elements to it, i get: Error: doc was not declared on the scope. And Error: root was not declared on the scope.

    But the qDebug is working fine. it is printing the message that it is suppose to print, depending on the variable append.

    And if i remove the whole if block and use the following, everything work fine, but it truncate the the file which i dnt want.

                file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text);
    
                QDomDocument doc("Products");
                QDomElement root = doc.createElement("Products");
                doc.appendChild(root);
    

    Can anybody tell me where a`im getting things wrong..

    JonBJ jsulmJ 2 Replies Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by mrjj
      #2

      Hi
      Your root and doc only exists within
      if (xxx)
      {
      } // scope ends and all is deleted

      Just move them above the if(append) so they are not deleted.

      If you need doc / root in more than one function, you can simply make them member of
      the class.

      1 Reply Last reply
      4
      • chawilaC chawila

        I have an xml file that was generated using c++.
        so i used it as a model in qml.
        now as the user is interacting with the App, i want to append to that xml in c++, then reload the xmlModel in qml.

        i tried these:

            QString filename= appFolder+"/db/"+xmlFile;
        
                if(append == true){
                    qDebug() << "appending...";
                    file.open(QIODevice::ReadWrite | QIODevice::Text);
                    QDomDocument doc;
                    doc.setContent(&file);
                    QDomNode root = doc.firstChild();
                    
                }else{
                    qDebug() << "trancating and adding to file..";
                    file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text);
                    QDomDocument doc("Products");
                    QDomElement root = doc.createElement("Products");
                    doc.appendChild(root);
                }
        

        Then i have a loop that should iterate while appending to the roort variable.
        So if i try to access the variable doc so that i can add elements to it, i get: Error: doc was not declared on the scope. And Error: root was not declared on the scope.

        But the qDebug is working fine. it is printing the message that it is suppose to print, depending on the variable append.

        And if i remove the whole if block and use the following, everything work fine, but it truncate the the file which i dnt want.

                    file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text);
        
                    QDomDocument doc("Products");
                    QDomElement root = doc.createElement("Products");
                    doc.appendChild(root);
        

        Can anybody tell me where a`im getting things wrong..

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #3

        @chawila said in Appending to xml:

        file.open(QIODevice::ReadWrite | QIODevice::Text)

        Take my observation with a pinch of salt, as I've never done any file IO in Qt! But when you want to append you have:

         file.open(QIODevice::ReadWrite | QIODevice::Text)
        

        Don't you need:

        file.open(QIODevice::ReadWrite | QIODevice::Append | QIODevice::Text)
        

        ? (Or at least some kind of "seek to end".) Else I would expect the write to be positioned initially at start of file, and you'll be writing new stuff all over existing content??

        [EDIT: Hmm, you might be relying on the QDomDocument to first read to end of file before you then do any writing? Sounds a bit scary/error-prone to me if so.]

        1 Reply Last reply
        2
        • chawilaC chawila

          I have an xml file that was generated using c++.
          so i used it as a model in qml.
          now as the user is interacting with the App, i want to append to that xml in c++, then reload the xmlModel in qml.

          i tried these:

              QString filename= appFolder+"/db/"+xmlFile;
          
                  if(append == true){
                      qDebug() << "appending...";
                      file.open(QIODevice::ReadWrite | QIODevice::Text);
                      QDomDocument doc;
                      doc.setContent(&file);
                      QDomNode root = doc.firstChild();
                      
                  }else{
                      qDebug() << "trancating and adding to file..";
                      file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text);
                      QDomDocument doc("Products");
                      QDomElement root = doc.createElement("Products");
                      doc.appendChild(root);
                  }
          

          Then i have a loop that should iterate while appending to the roort variable.
          So if i try to access the variable doc so that i can add elements to it, i get: Error: doc was not declared on the scope. And Error: root was not declared on the scope.

          But the qDebug is working fine. it is printing the message that it is suppose to print, depending on the variable append.

          And if i remove the whole if block and use the following, everything work fine, but it truncate the the file which i dnt want.

                      file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text);
          
                      QDomDocument doc("Products");
                      QDomElement root = doc.createElement("Products");
                      doc.appendChild(root);
          

          Can anybody tell me where a`im getting things wrong..

          jsulmJ Offline
          jsulmJ Offline
          jsulm
          Lifetime Qt Champion
          wrote on last edited by jsulm
          #4

          @chawila said in Appending to xml:

          And if i remove the whole if block and use the following, everything work fine, but it truncate the the file which i dnt want.
          file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text);

          Sure it truncates the file as you tell it to do so by using QIODevice::Truncate. Actually you should write the whole file again after changing XML, for that just don't pass QIODevice::Truncate.

          https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #5

            Be careful you understand what's going going on with truncate/append if you follow @jsulm 's advice.

            If you open an existing file for write or read/write with content, and you do not pass in either QIODevice::Truncate or QIODevice::Append, if you start writing to it you do start overwriting the content from the start but the file's length remains as it was when you opened it. If the total number of bytes you write is then less than the current content number of bytes, the remaining content after what you have written remains at the end of file. Which is most unlikely to be what you want! Since in this situation you are never wanting to actually open the file for random access read/write (like a database would), I would expect your open for write to always have one of QIODevice::Truncate or QIODevice::Append.

            Your use of QIODevice::ReadWrite concerns me, because writing will happen immediately after wherever you last read from, and if you're not careful/don't know for sure where that is you may be writing into the middle of the document. I admit I don't know just how QDomDocument attaches to the file you give it, but my inclination would not to have read/write here. Get your reading done via QIODevice::Read, then either rewrite (with truncate) the whole file with old content + new or open it for append and output just the new stuff. IMHO.

            BTW, while I think of it, it's most unusual to be able to simply append to an XML file. If your XML file has one root element, like <root>...</root>, which is what most XML documents look like, then you can never just append, as any extra content will need to come before the closing </root> at end of file. The only time you can append is if the doc has no/multiple root element, so from the top-level it looks like <node>...</node><node>...</node>... with nothing enclosing them all. Is that indeed the case for your document?

            1 Reply Last reply
            1
            • chawilaC Offline
              chawilaC Offline
              chawila
              wrote on last edited by
              #6

              @JNBarchan
              yah. thanks, i can`t believe i forgot that.

              @mrjj
              Thanks for that man. yah thedoc and root variable were out of scope, so i made the class properties..


              But it looks like it can`t read from the file( when i try to append) so it give me error: Calling appendChild() on a null node does nothing.
              So i think there is something wrong with the way i read from the file..

              JonBJ 1 Reply Last reply
              0
              • chawilaC chawila

                @JNBarchan
                yah. thanks, i can`t believe i forgot that.

                @mrjj
                Thanks for that man. yah thedoc and root variable were out of scope, so i made the class properties..


                But it looks like it can`t read from the file( when i try to append) so it give me error: Calling appendChild() on a null node does nothing.
                So i think there is something wrong with the way i read from the file..

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by JonB
                #7

                @chawila said in Appending to xml:

                But it looks like it can`t read from the file( when i try to append) so it give me error: Calling appendChild() on a null node does nothing.
                So i think there is something wrong with the way i read from the file..

                Well the appendChild() is to do with the QDomDocument state and appending a new node to it, rather than reading from file. From the error message, it is unclear to me which, but you are doing one of NULL->appendChild(something) or something->appendChild(NULL).

                What about answering whether the document does or does not have a single root node? Because if it does not, the whole business of trying to "append" is a non-starter.

                1 Reply Last reply
                0
                • chawilaC Offline
                  chawilaC Offline
                  chawila
                  wrote on last edited by chawila
                  #8

                  I think these might give u the answer u`re looking for

                  <Products>
                  
                   <Product>
                    <prId>2506</prId>
                    <spIcon>e19ea7d081f8782ac41269ac9268e52c.jpeg</spIcon>
                    <prThumb>d044d922d380359eec7452cc751a9d2c.jpeg</prThumb>
                    <prName> toilet tissue twinsaver baby soft 18s</prName>
                    <saved>0</saved>
                    <price>65.95</price>
                   </Product>
                  
                  </Products>
                  

                  These gives me failed(when appending):

                          if(append == true){
                              qDebug() << "appending";
                              file.open(QIODevice::ReadWrite | QIODevice::Append | QIODevice::Text);
                  
                               if(doc.setContent(&file)){
                                   qDebug() << "read.";
                               }else{
                                   qDebug() << "failed";
                               }
                               root = doc.firstChildElement("Products");
                  
                          }else{
                              qDebug() << "truncating..";
                  
                              file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text);
                              qDebug() << "file open..";
                              root = doc.createElement("Products");
                              doc.appendChild(root);
                  
                          }
                  
                  

                  Then

                  QDomElement productTag = doc.createElement("Product");
                  qDebug() << "appending Product tag";
                  root.appendChild(productTag );
                  
                  
                  JonBJ 1 Reply Last reply
                  0
                  • chawilaC chawila

                    I think these might give u the answer u`re looking for

                    <Products>
                    
                     <Product>
                      <prId>2506</prId>
                      <spIcon>e19ea7d081f8782ac41269ac9268e52c.jpeg</spIcon>
                      <prThumb>d044d922d380359eec7452cc751a9d2c.jpeg</prThumb>
                      <prName> toilet tissue twinsaver baby soft 18s</prName>
                      <saved>0</saved>
                      <price>65.95</price>
                     </Product>
                    
                    </Products>
                    

                    These gives me failed(when appending):

                            if(append == true){
                                qDebug() << "appending";
                                file.open(QIODevice::ReadWrite | QIODevice::Append | QIODevice::Text);
                    
                                 if(doc.setContent(&file)){
                                     qDebug() << "read.";
                                 }else{
                                     qDebug() << "failed";
                                 }
                                 root = doc.firstChildElement("Products");
                    
                            }else{
                                qDebug() << "truncating..";
                    
                                file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text);
                                qDebug() << "file open..";
                                root = doc.createElement("Products");
                                doc.appendChild(root);
                    
                            }
                    
                    

                    Then

                    QDomElement productTag = doc.createElement("Product");
                    qDebug() << "appending Product tag";
                    root.appendChild(productTag );
                    
                    
                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by JonB
                    #9

                    @chawila said in Appending to xml:

                    firstChildElement

                    1. Check the return result of root = doc.firstChildElement("Products"); before root.appendChild(productTag ) ?
                    2. Try QDomElement root = doc.documentElement(); instead of doc.firstChildElement("Products")?
                    3. Do you understand that the whole principle of appending with QIODevice::Append to the document file in order to create a new Product is never going to work, because you need that new node to go inside the Products node in any case?
                    1 Reply Last reply
                    0
                    • chawilaC Offline
                      chawilaC Offline
                      chawila
                      wrote on last edited by
                      #10

                      @JNBarchan

                      itried it still get: Calling appendChild() on a null node does nothing.
                      So what are u suggesting about QIODevice::Append.

                      JonBJ 1 Reply Last reply
                      0
                      • chawilaC chawila

                        @JNBarchan

                        itried it still get: Calling appendChild() on a null node does nothing.
                        So what are u suggesting about QIODevice::Append.

                        JonBJ Offline
                        JonBJ Offline
                        JonB
                        wrote on last edited by JonB
                        #11

                        @chawila said in Appending to xml:

                        @JNBarchan

                        itried it still get: Calling appendChild() on a null node does nothing.

                        So for your root.appendChild(productTag ), debug out both root & productTag?

                        So what are u suggesting about QIODevice::Append.

                        For what you want to do, you cannot use root.appendChild(productTag ) and you cannot "append to the existing XML in the file" in any shape or form. I think from what you're saying you want to:

                        1. Read in the whole existing XML file to create the document.
                        2. Do your code which alters the DOM by appending new nodes or whatever.
                        3. Overwrite the complete file with the serialization of the complete DOM document, i.e. no appending, just like creating it from scratch.
                        1 Reply Last reply
                        0
                        • chawilaC Offline
                          chawilaC Offline
                          chawila
                          wrote on last edited by
                          #12

                          @JNBarchan
                          I got compilation Error:

                          No match for 'operator'<<(operand types are 'QDeburg' and QDomElement')
                                 qDebug() << root << productTag ;
                          

                          So how can i do that?..

                          • Read in the whole existing XML file to create the document.

                          • Do your code which alters the DOM by appending new nodes or whatever.

                          • Overwrite the complete file with the serialization of the complete DOM document, i.e. no appending, just like creating it from scratch.

                          JonBJ 1 Reply Last reply
                          0
                          • chawilaC chawila

                            @JNBarchan
                            I got compilation Error:

                            No match for 'operator'<<(operand types are 'QDeburg' and QDomElement')
                                   qDebug() << root << productTag ;
                            

                            So how can i do that?..

                            • Read in the whole existing XML file to create the document.

                            • Do your code which alters the DOM by appending new nodes or whatever.

                            • Overwrite the complete file with the serialization of the complete DOM document, i.e. no appending, just like creating it from scratch.

                            JonBJ Offline
                            JonBJ Offline
                            JonB
                            wrote on last edited by JonB
                            #13

                            @chawila
                            Outline code:

                            if (append)
                            {
                              openFileForReadOnly();
                              readFileToCreateDOM();
                              closeFile();
                            }
                            else
                            {
                              createNewEmptyDom();
                              possiblyCreateEmptyProductsNode();
                            }
                            doCodeToPutNewProductNodesUnderProductsNode();
                            saveWholeDOMDocumentToFileWithOverwrite();
                            

                            No ReadWrites or Appends ; Truncate only used in saveWholeDOMDocumentToFileWithOverwrite() if that's what is required to overwrite. See e.g. https://forum.qt.io/topic/43724/solved-save-qdomdocument-to-xml or http://www.qtforum.org/article/2756/how-to-qdomdocument-to-file.html. e.g. file.open( QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text ) when you're ready to overwrite.

                            1 Reply Last reply
                            0
                            • chawilaC Offline
                              chawilaC Offline
                              chawila
                              wrote on last edited by
                              #14

                              @JNBarchan

                              So all these:

                                openFileForReadOnly();
                                readFileToCreateDOM();
                              //-----------------------
                                createNewEmptyDom();
                                possiblyCreateEmptyProductsNode();
                              //--------------------
                              doCodeToPutNewProductNodesUnderProductsNode();
                              saveWholeDOMDocumentToFileWithOverwrite();
                              

                              Are methods/functions i should create

                              JonBJ 1 Reply Last reply
                              0
                              • chawilaC chawila

                                @JNBarchan

                                So all these:

                                  openFileForReadOnly();
                                  readFileToCreateDOM();
                                //-----------------------
                                  createNewEmptyDom();
                                  possiblyCreateEmptyProductsNode();
                                //--------------------
                                doCodeToPutNewProductNodesUnderProductsNode();
                                saveWholeDOMDocumentToFileWithOverwrite();
                                

                                Are methods/functions i should create

                                JonBJ Offline
                                JonBJ Offline
                                JonB
                                wrote on last edited by JonB
                                #15

                                @chawila
                                Well, yes!
                                For:

                                  createNewEmptyDom();
                                  possiblyCreateEmptyProductsNode();
                                

                                you already had:

                                     root = doc.createElement("Products");
                                     doc.appendChild(root);
                                

                                (provided your DOM doc starts out empty).

                                BTW

                                QIODevice::WriteOnly 0x0002 The device is open for writing. Note that this mode implies Truncate.

                                1 Reply Last reply
                                0
                                • chawilaC Offline
                                  chawilaC Offline
                                  chawila
                                  wrote on last edited by
                                  #16

                                  @JNBarchan
                                  Ok i`ll keep on trying,
                                  but u are giving me a big task(reaserch) to do..

                                  JonBJ 1 Reply Last reply
                                  0
                                  • chawilaC chawila

                                    @JNBarchan
                                    Ok i`ll keep on trying,
                                    but u are giving me a big task(reaserch) to do..

                                    JonBJ Offline
                                    JonBJ Offline
                                    JonB
                                    wrote on last edited by JonB
                                    #17

                                    @chawila
                                    Sorry, I don't see any "big task" or "research" for you to do?
                                    You already seem to know how to read a file to QDomDocument, add nodes to it, and write it out, that's all we're doing.

                                    1 Reply Last reply
                                    0
                                    • chawilaC Offline
                                      chawilaC Offline
                                      chawila
                                      wrote on last edited by
                                      #18

                                      @JNBarchan
                                      Let me get into it i`ll be back, hopefully with good news..

                                      JonBJ 1 Reply Last reply
                                      0
                                      • chawilaC chawila

                                        @JNBarchan
                                        Let me get into it i`ll be back, hopefully with good news..

                                        JonBJ Offline
                                        JonBJ Offline
                                        JonB
                                        wrote on last edited by JonB
                                        #19

                                        @chawila
                                        It is your use of "append to xml file" that is faulty. To add new nodes, you do not literally "append" them to the whole file, you add (append/insert) them near the end of the file but not literally at the end of the file.

                                        P.S.
                                        You can probably use QDomDocument::save(QTextStream) as one way of saving the dom doc back to file, if you like.

                                        1 Reply Last reply
                                        0
                                        • chawilaC Offline
                                          chawilaC Offline
                                          chawila
                                          wrote on last edited by
                                          #20

                                          @JNBarchan
                                          Thanks,
                                          it was little bit challenging though..

                                          JonBJ 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