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. Modify an XML file with QDomDocument
Forum Update on Monday, May 27th 2025

Modify an XML file with QDomDocument

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 3 Posters 628 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.
  • C Offline
    C Offline
    Ceng0
    wrote on 8 Feb 2024, 08:42 last edited by Ceng0 2 Aug 2024, 08:43
    #1

    Hi,

    I am modifying an XML file using QDomDocument.

    • When I want to update the xml file, it adds the xmlns attribute to each tag.

    • I have tried to remove the xmlns tag by navigating through each tag, but it cannot remove it because it cannot find the xmlns tag in the items.

    • QDomElement works as if there is no xmlns tag in the generatorElement content, but when I want to write to the file, it adds the xmlns tag. How can I fix it?

    Xml file:

    <?xml version="1.0" encoding="UTF-8"?>
    <entity xmlns="http://www.sample.com.tr/EntityConfSchema" xmlns:attr="http://www.sample.com.tr/AttributeTypes" xmlns:sim="http://www.sample.com.tr/DataTypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <sample-info>
       	<sample-type>1111111</sample-type>
       </sample-info>
       <sample-initials>
       	<attribute-nvp name="sampleName">
       		<attribute xsi:type="attr:StringAttribute" value="sampleValue"/>
       	</attribute-nvp>
       	<attribute-nvp name="sampleName">
       		<attribute xsi:type="attr:StringAttribute" value="sampleValue"/>
       	</attribute-nvp>
       	<attribute-nvp name="sampleName">
       		<attribute xsi:type="attr:StringAttribute" value="sampleValue"/>
       	</attribute-nvp>
       </sample-initials>
    </entity>
    

    Here's my code:

    void SampleWidget::on_pushButtonSave_clicked()
    {
        QString entityCurrentFile = "sampleFile.entity";
        QString fileToCopy = "fileToCopy.entity";
    
        if (QFile::exists(entityCurrentFile))
        {
            QFile::remove(entityCurrentFile);
        }
    
        QFile::copy(fileToCopy , entityCurrentFile);
    
        QFile file(entityCurrentFile);
        if (!file.open(QIODevice::ReadWrite | QIODevice::Text))
        {
            SIM_LOG_ERROR("CANNOT OPEN");
            return;
        }
    
        QDomDocument* generatorDocument = new QDomDocument;
        if (!generatorDocument->setContent(&file, true))
        {
            return;
        }
    
        file.close();
    
    //checked the xmlData , it appears to be corrupted. There is xmlns attribute in every tag
        QByteArray xmlData = generatorDocument->toByteArray();
    
    
        QDomElement generatorElement = generatorDocument->documentElement();
    
        removeXmlnsAttributesFromDocument(generatorElement);
    
        modifyEntityFile(generatorElement);   // modify 
    
        QFile outputFile(entityCurrentFile);
        // Save content back to the file
        if (!outputFile.open(QIODevice::Truncate | QIODevice::WriteOnly)) {
            return;
        }
        QTextStream stream(&outputFile);
        stream << generatorDocument->toByteArray();
        QByteArray xmlData = generatorDocument->toByteArray();
        outputFile.close();
    }
    
    void SampleWidget::removeXmlnsAttributesFromDocument(QDomNode& node)
    {
        QDomNodeList children = node.childNodes();
    
        for (int i = 0; i < children.size(); ++i) {
            QDomNode childNode = children.at(i);
    
            if (childNode.isElement()) {
                QDomElement element = childNode.toElement();
                QString attributeName = "xmlns";
    
                if (element.hasAttribute(attributeName)) {
                    element.removeAttribute(attributeName);
                    qDebug() << "Attribute" << attributeName << "removed from node" << attributeName;
                }
                else {
                    qDebug() << "Node" << attributeName << "does not have attribute" << attributeName;
                }
            }
    
            removeXmlnsAttributesFromDocument(childNode);
        }
    }
    

    Result:

    <?xml version="1.0" encoding="UTF-8"?>
    <entity xmlns="http://www.sample.com.tr/EntityConfSchema">
    	<sample-info xmlns="http://www.sample.com.tr/EntityConfSchema">
    		<sample-type xmlns="http://www.sample.com.tr/EntityConfSchema">111111</sample-type>
    	</sample-info>
    	<sample-initials xmlns="http://www.sample.com.tr/EntityConfSchema">
    		<attribute-nvp xmlns="http://www.sample.com.tr/EntityConfSchema" name="ExampleName">
    			<attribute xmlns="http://www.sample.com.tr/EntityConfSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:type="attr:StringAttribute" value="ExampleValue"/>
    		</attribute-nvp>
    		<attribute-nvp xmlns="http://www.sample.com.tr/EntityConfSchema"  name="ExampleName">
    			<attribute xmlns="http://www.sample.com.tr/EntityConfSchema"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="attr:StringAttribute" value="ExampleValue"/>
    		</attribute-nvp>
    		<attribute-nvp xmlns="http://www.sample.com.tr/EntityConfSchema"  name="ExampleName">
    			<attribute xmlns="http://www.sample.com.tr/EntityConfSchema"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="attr:StringAttribute" value="ExampleValue"/>
    		</attribute-nvp>
    	</sample-initials>
    </entity>
    

    Expected xml file:

    <?xml version="1.0" encoding="UTF-8"?>
    <entity xmlns="http://www.sample.com.tr/EntityConfSchema" xmlns:attr="http://www.sample.com.tr/AttributeTypes" xmlns:sim="http://www.sample.com.tr/DataTypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    	<sample-info>
    		<sample-type>88888888</sample-type>
    	</sample-info>
    	<sample-initials>
    		<attribute-nvp name="ExampleName">
    			<attribute xsi:type="attr:StringAttribute" value="ExampleValue"/>
    		</attribute-nvp>
    		<attribute-nvp name="ExampleName">
    			<attribute xsi:type="attr:StringAttribute" value="ExampleValue"/>
    		</attribute-nvp>
    		<attribute-nvp name="ExampleName">
    			<attribute xsi:type="attr:StringAttribute" value="ExampleValue"/>
    		</attribute-nvp>
    	</sample-initials>
    </entity>
    
    J C 2 Replies Last reply 8 Feb 2024, 14:32
    0
    • C Ceng0
      8 Feb 2024, 08:42

      Hi,

      I am modifying an XML file using QDomDocument.

      • When I want to update the xml file, it adds the xmlns attribute to each tag.

      • I have tried to remove the xmlns tag by navigating through each tag, but it cannot remove it because it cannot find the xmlns tag in the items.

      • QDomElement works as if there is no xmlns tag in the generatorElement content, but when I want to write to the file, it adds the xmlns tag. How can I fix it?

      Xml file:

      <?xml version="1.0" encoding="UTF-8"?>
      <entity xmlns="http://www.sample.com.tr/EntityConfSchema" xmlns:attr="http://www.sample.com.tr/AttributeTypes" xmlns:sim="http://www.sample.com.tr/DataTypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
         <sample-info>
         	<sample-type>1111111</sample-type>
         </sample-info>
         <sample-initials>
         	<attribute-nvp name="sampleName">
         		<attribute xsi:type="attr:StringAttribute" value="sampleValue"/>
         	</attribute-nvp>
         	<attribute-nvp name="sampleName">
         		<attribute xsi:type="attr:StringAttribute" value="sampleValue"/>
         	</attribute-nvp>
         	<attribute-nvp name="sampleName">
         		<attribute xsi:type="attr:StringAttribute" value="sampleValue"/>
         	</attribute-nvp>
         </sample-initials>
      </entity>
      

      Here's my code:

      void SampleWidget::on_pushButtonSave_clicked()
      {
          QString entityCurrentFile = "sampleFile.entity";
          QString fileToCopy = "fileToCopy.entity";
      
          if (QFile::exists(entityCurrentFile))
          {
              QFile::remove(entityCurrentFile);
          }
      
          QFile::copy(fileToCopy , entityCurrentFile);
      
          QFile file(entityCurrentFile);
          if (!file.open(QIODevice::ReadWrite | QIODevice::Text))
          {
              SIM_LOG_ERROR("CANNOT OPEN");
              return;
          }
      
          QDomDocument* generatorDocument = new QDomDocument;
          if (!generatorDocument->setContent(&file, true))
          {
              return;
          }
      
          file.close();
      
      //checked the xmlData , it appears to be corrupted. There is xmlns attribute in every tag
          QByteArray xmlData = generatorDocument->toByteArray();
      
      
          QDomElement generatorElement = generatorDocument->documentElement();
      
          removeXmlnsAttributesFromDocument(generatorElement);
      
          modifyEntityFile(generatorElement);   // modify 
      
          QFile outputFile(entityCurrentFile);
          // Save content back to the file
          if (!outputFile.open(QIODevice::Truncate | QIODevice::WriteOnly)) {
              return;
          }
          QTextStream stream(&outputFile);
          stream << generatorDocument->toByteArray();
          QByteArray xmlData = generatorDocument->toByteArray();
          outputFile.close();
      }
      
      void SampleWidget::removeXmlnsAttributesFromDocument(QDomNode& node)
      {
          QDomNodeList children = node.childNodes();
      
          for (int i = 0; i < children.size(); ++i) {
              QDomNode childNode = children.at(i);
      
              if (childNode.isElement()) {
                  QDomElement element = childNode.toElement();
                  QString attributeName = "xmlns";
      
                  if (element.hasAttribute(attributeName)) {
                      element.removeAttribute(attributeName);
                      qDebug() << "Attribute" << attributeName << "removed from node" << attributeName;
                  }
                  else {
                      qDebug() << "Node" << attributeName << "does not have attribute" << attributeName;
                  }
              }
      
              removeXmlnsAttributesFromDocument(childNode);
          }
      }
      

      Result:

      <?xml version="1.0" encoding="UTF-8"?>
      <entity xmlns="http://www.sample.com.tr/EntityConfSchema">
      	<sample-info xmlns="http://www.sample.com.tr/EntityConfSchema">
      		<sample-type xmlns="http://www.sample.com.tr/EntityConfSchema">111111</sample-type>
      	</sample-info>
      	<sample-initials xmlns="http://www.sample.com.tr/EntityConfSchema">
      		<attribute-nvp xmlns="http://www.sample.com.tr/EntityConfSchema" name="ExampleName">
      			<attribute xmlns="http://www.sample.com.tr/EntityConfSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:type="attr:StringAttribute" value="ExampleValue"/>
      		</attribute-nvp>
      		<attribute-nvp xmlns="http://www.sample.com.tr/EntityConfSchema"  name="ExampleName">
      			<attribute xmlns="http://www.sample.com.tr/EntityConfSchema"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="attr:StringAttribute" value="ExampleValue"/>
      		</attribute-nvp>
      		<attribute-nvp xmlns="http://www.sample.com.tr/EntityConfSchema"  name="ExampleName">
      			<attribute xmlns="http://www.sample.com.tr/EntityConfSchema"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="attr:StringAttribute" value="ExampleValue"/>
      		</attribute-nvp>
      	</sample-initials>
      </entity>
      

      Expected xml file:

      <?xml version="1.0" encoding="UTF-8"?>
      <entity xmlns="http://www.sample.com.tr/EntityConfSchema" xmlns:attr="http://www.sample.com.tr/AttributeTypes" xmlns:sim="http://www.sample.com.tr/DataTypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      	<sample-info>
      		<sample-type>88888888</sample-type>
      	</sample-info>
      	<sample-initials>
      		<attribute-nvp name="ExampleName">
      			<attribute xsi:type="attr:StringAttribute" value="ExampleValue"/>
      		</attribute-nvp>
      		<attribute-nvp name="ExampleName">
      			<attribute xsi:type="attr:StringAttribute" value="ExampleValue"/>
      		</attribute-nvp>
      		<attribute-nvp name="ExampleName">
      			<attribute xsi:type="attr:StringAttribute" value="ExampleValue"/>
      		</attribute-nvp>
      	</sample-initials>
      </entity>
      
      J Offline
      J Offline
      JonB
      wrote on 8 Feb 2024, 14:32 last edited by JonB 2 Aug 2024, 14:39
      #2

      @Ceng0
      I have had a look at this.

      The text it saves may not be what you or I, as humans, would like, but it is still "correct".

      It chooses to repeat the namespace attributes on each element. I believe this is deliberate/hard-coded, so that it is always right. I came across somewhere (e.g. https://codebrowser.dev/qt5/qtbase/src/xml/dom/qdom.cpp.html#_ZNK15QDomAttrPrivate4saveER11QTextStreamii):

           * QDomElementPrivate::save() output a namespace declaration if
           * the element is in a namespace, no matter what
      

      What it is not doing is taking into account default namespace, which we would like it to do. I have not found any handling for this or way of forcing it. I agree there is some special handling where we cannot see these as attribute nodes after reading.

      If you passed false instead of true to setContent() you would get the original document content back as-was. You would also see the original attributes retained. I do not know if you can work with that --- depends what you are doing with/to the document --- but that is the simplest and may be only way.

      You might alternatively do your own writing via QXmlStreamWriter to get control over this, but I think that's quite a bit work and seems silly if you have a QDomDocument.

      1 Reply Last reply
      1
      • C Ceng0
        8 Feb 2024, 08:42

        Hi,

        I am modifying an XML file using QDomDocument.

        • When I want to update the xml file, it adds the xmlns attribute to each tag.

        • I have tried to remove the xmlns tag by navigating through each tag, but it cannot remove it because it cannot find the xmlns tag in the items.

        • QDomElement works as if there is no xmlns tag in the generatorElement content, but when I want to write to the file, it adds the xmlns tag. How can I fix it?

        Xml file:

        <?xml version="1.0" encoding="UTF-8"?>
        <entity xmlns="http://www.sample.com.tr/EntityConfSchema" xmlns:attr="http://www.sample.com.tr/AttributeTypes" xmlns:sim="http://www.sample.com.tr/DataTypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
           <sample-info>
           	<sample-type>1111111</sample-type>
           </sample-info>
           <sample-initials>
           	<attribute-nvp name="sampleName">
           		<attribute xsi:type="attr:StringAttribute" value="sampleValue"/>
           	</attribute-nvp>
           	<attribute-nvp name="sampleName">
           		<attribute xsi:type="attr:StringAttribute" value="sampleValue"/>
           	</attribute-nvp>
           	<attribute-nvp name="sampleName">
           		<attribute xsi:type="attr:StringAttribute" value="sampleValue"/>
           	</attribute-nvp>
           </sample-initials>
        </entity>
        

        Here's my code:

        void SampleWidget::on_pushButtonSave_clicked()
        {
            QString entityCurrentFile = "sampleFile.entity";
            QString fileToCopy = "fileToCopy.entity";
        
            if (QFile::exists(entityCurrentFile))
            {
                QFile::remove(entityCurrentFile);
            }
        
            QFile::copy(fileToCopy , entityCurrentFile);
        
            QFile file(entityCurrentFile);
            if (!file.open(QIODevice::ReadWrite | QIODevice::Text))
            {
                SIM_LOG_ERROR("CANNOT OPEN");
                return;
            }
        
            QDomDocument* generatorDocument = new QDomDocument;
            if (!generatorDocument->setContent(&file, true))
            {
                return;
            }
        
            file.close();
        
        //checked the xmlData , it appears to be corrupted. There is xmlns attribute in every tag
            QByteArray xmlData = generatorDocument->toByteArray();
        
        
            QDomElement generatorElement = generatorDocument->documentElement();
        
            removeXmlnsAttributesFromDocument(generatorElement);
        
            modifyEntityFile(generatorElement);   // modify 
        
            QFile outputFile(entityCurrentFile);
            // Save content back to the file
            if (!outputFile.open(QIODevice::Truncate | QIODevice::WriteOnly)) {
                return;
            }
            QTextStream stream(&outputFile);
            stream << generatorDocument->toByteArray();
            QByteArray xmlData = generatorDocument->toByteArray();
            outputFile.close();
        }
        
        void SampleWidget::removeXmlnsAttributesFromDocument(QDomNode& node)
        {
            QDomNodeList children = node.childNodes();
        
            for (int i = 0; i < children.size(); ++i) {
                QDomNode childNode = children.at(i);
        
                if (childNode.isElement()) {
                    QDomElement element = childNode.toElement();
                    QString attributeName = "xmlns";
        
                    if (element.hasAttribute(attributeName)) {
                        element.removeAttribute(attributeName);
                        qDebug() << "Attribute" << attributeName << "removed from node" << attributeName;
                    }
                    else {
                        qDebug() << "Node" << attributeName << "does not have attribute" << attributeName;
                    }
                }
        
                removeXmlnsAttributesFromDocument(childNode);
            }
        }
        

        Result:

        <?xml version="1.0" encoding="UTF-8"?>
        <entity xmlns="http://www.sample.com.tr/EntityConfSchema">
        	<sample-info xmlns="http://www.sample.com.tr/EntityConfSchema">
        		<sample-type xmlns="http://www.sample.com.tr/EntityConfSchema">111111</sample-type>
        	</sample-info>
        	<sample-initials xmlns="http://www.sample.com.tr/EntityConfSchema">
        		<attribute-nvp xmlns="http://www.sample.com.tr/EntityConfSchema" name="ExampleName">
        			<attribute xmlns="http://www.sample.com.tr/EntityConfSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:type="attr:StringAttribute" value="ExampleValue"/>
        		</attribute-nvp>
        		<attribute-nvp xmlns="http://www.sample.com.tr/EntityConfSchema"  name="ExampleName">
        			<attribute xmlns="http://www.sample.com.tr/EntityConfSchema"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="attr:StringAttribute" value="ExampleValue"/>
        		</attribute-nvp>
        		<attribute-nvp xmlns="http://www.sample.com.tr/EntityConfSchema"  name="ExampleName">
        			<attribute xmlns="http://www.sample.com.tr/EntityConfSchema"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="attr:StringAttribute" value="ExampleValue"/>
        		</attribute-nvp>
        	</sample-initials>
        </entity>
        

        Expected xml file:

        <?xml version="1.0" encoding="UTF-8"?>
        <entity xmlns="http://www.sample.com.tr/EntityConfSchema" xmlns:attr="http://www.sample.com.tr/AttributeTypes" xmlns:sim="http://www.sample.com.tr/DataTypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        	<sample-info>
        		<sample-type>88888888</sample-type>
        	</sample-info>
        	<sample-initials>
        		<attribute-nvp name="ExampleName">
        			<attribute xsi:type="attr:StringAttribute" value="ExampleValue"/>
        		</attribute-nvp>
        		<attribute-nvp name="ExampleName">
        			<attribute xsi:type="attr:StringAttribute" value="ExampleValue"/>
        		</attribute-nvp>
        		<attribute-nvp name="ExampleName">
        			<attribute xsi:type="attr:StringAttribute" value="ExampleValue"/>
        		</attribute-nvp>
        	</sample-initials>
        </entity>
        
        C Offline
        C Offline
        ChrisW67
        wrote on 9 Feb 2024, 06:55 last edited by ChrisW67 2 Sept 2024, 06:56
        #3

        @Ceng0
        I assume that you are using Qt 5 because in Qt 6 the second argument to QDomDocument::setContent() is not a bool.

        Depending on your actual requirements you may be able to achieve the desired result without turning on namespace handling. This, for example, modifies the document but does not add namespace attribute everywhere:

        #include <QCoreApplication>
        #include <QDomDocument>
        #include <QFile>
        
        int main(int argc, char** argv) {
                QCoreApplication app(argc, argv);
        
                QFile file("input.xml");
                if (file.open(QIODevice::ReadOnly)) {
                        QDomDocument doc;
                        doc.setContent(&file, false);
        
                        QDomElement docElem = doc.documentElement();
                        QDomElement first = docElem.firstChildElement("sample-initials");
                        first.setAttribute("xyzzy", "plugh");
        
                        QFile out("output.xml");
                        if (out.open(QIODevice::WriteOnly)) {
                                out.write(doc.toByteArray(2));
                        }
                }
        
                return 0;
        }
        

        Edit: Oops, just noticed that JonB already suggested this

        J 1 Reply Last reply 9 Feb 2024, 09:16
        0
        • C ChrisW67
          9 Feb 2024, 06:55

          @Ceng0
          I assume that you are using Qt 5 because in Qt 6 the second argument to QDomDocument::setContent() is not a bool.

          Depending on your actual requirements you may be able to achieve the desired result without turning on namespace handling. This, for example, modifies the document but does not add namespace attribute everywhere:

          #include <QCoreApplication>
          #include <QDomDocument>
          #include <QFile>
          
          int main(int argc, char** argv) {
                  QCoreApplication app(argc, argv);
          
                  QFile file("input.xml");
                  if (file.open(QIODevice::ReadOnly)) {
                          QDomDocument doc;
                          doc.setContent(&file, false);
          
                          QDomElement docElem = doc.documentElement();
                          QDomElement first = docElem.firstChildElement("sample-initials");
                          first.setAttribute("xyzzy", "plugh");
          
                          QFile out("output.xml");
                          if (out.open(QIODevice::WriteOnly)) {
                                  out.write(doc.toByteArray(2));
                          }
                  }
          
                  return 0;
          }
          

          Edit: Oops, just noticed that JonB already suggested this

          J Offline
          J Offline
          JonB
          wrote on 9 Feb 2024, 09:16 last edited by
          #4

          @ChrisW67 said in Modify an XML file with QDomDocument:

          doc.setContent(&file, false);

          Yes, that is the false for "namespace processing" I was suggesting, which would be by far the simplest. Then everything stays like it is.

          But it depends on what the OP wants to do with the document read in (e.g. searching it?), if there are other namespaces involved, if they want to insert new nodes, etc.

          C 1 Reply Last reply 22 Mar 2024, 07:00
          0
          • J JonB
            9 Feb 2024, 09:16

            @ChrisW67 said in Modify an XML file with QDomDocument:

            doc.setContent(&file, false);

            Yes, that is the false for "namespace processing" I was suggesting, which would be by far the simplest. Then everything stays like it is.

            But it depends on what the OP wants to do with the document read in (e.g. searching it?), if there are other namespaces involved, if they want to insert new nodes, etc.

            C Offline
            C Offline
            Ceng0
            wrote on 22 Mar 2024, 07:00 last edited by
            #5

            @JonB Sorry for the late reply

            doc.setContent(&file, false); works for me. Thank you .

            1 Reply Last reply
            0
            • C Ceng0 has marked this topic as solved on 25 Mar 2024, 10:53

            • Login

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