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. QDomElement, how to get these?

QDomElement, how to get these?

Scheduled Pinned Locked Moved Unsolved General and Desktop
10 Posts 2 Posters 1.2k Views 1 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.
  • SPlattenS Offline
    SPlattenS Offline
    SPlatten
    wrote on last edited by SPlatten
    #1

    I have written code to extract the attributes and nodes from an XML document, now I want to add support for nodes that may contain comments, scripts or text.

    I thought the nodeType would identify these, however it doesn't, how do I extract these items?

    I tried using the text function, but it returns not only the content between the node being checked but everything in the document.

    Kind Regards,
    Sy

    JonBJ 1 Reply Last reply
    0
    • SPlattenS SPlatten

      I have written code to extract the attributes and nodes from an XML document, now I want to add support for nodes that may contain comments, scripts or text.

      I thought the nodeType would identify these, however it doesn't, how do I extract these items?

      I tried using the text function, but it returns not only the content between the node being checked but everything in the document.

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

      @SPlatten
      You must switch on the QDomNode::NodeType QDomNode::nodeType() const, which returns one the types in enum QDomNode::NodeType, to do your parsing correctly.

      I have a feeling you are calling QString QDomElement::text() const. This is a "convenience" function which generates the textual content of any QDomElement regardless of its real type, and is not suitable for your purposes. ["The text() function operates recursively to find the text (since not all elements contain text)."] Note that for what you are doing you need to work from QDomNodes, not QDomElements.

      SPlattenS 1 Reply Last reply
      3
      • JonBJ JonB

        @SPlatten
        You must switch on the QDomNode::NodeType QDomNode::nodeType() const, which returns one the types in enum QDomNode::NodeType, to do your parsing correctly.

        I have a feeling you are calling QString QDomElement::text() const. This is a "convenience" function which generates the textual content of any QDomElement regardless of its real type, and is not suitable for your purposes. ["The text() function operates recursively to find the text (since not all elements contain text)."] Note that for what you are doing you need to work from QDomNodes, not QDomElements.

        SPlattenS Offline
        SPlattenS Offline
        SPlatten
        wrote on last edited by
        #3

        @JonB , I am doing exactly that in my function, I've single stepped through the function and I don't see any type other than QDomNode::ElementNode.

        Here is my code:

        QDomElement objElement = objXML.documentElement();
        QJsonObject objResponse;
        asTree(objElement, objResponse);
        

        The asTree function is called recursively:

        void clsModXML::asTree(QDomElement& robjElement, QJsonObject& robjResult) {
            QDomNode::NodeType eNodeType = robjElement.nodeType();
        
            if ( eNodeType != QDomNode::ElementNode ) {
        //I have a breakpoint here and it never gets here!
                return;
            }
            QDomNamedNodeMap mpAttr = robjElement.attributes();
            QJsonObject objAttr;
            for( int i=0; i<mpAttr.size(); i++ ) {
                QDomNode item(mpAttr.item(i));
                eNodeType = item.nodeType();
        
                if ( eNodeType != QDomNode::AttributeNode ) {
                    continue;
                }
                objAttr.insert(item.nodeName(), item.nodeValue());
            }
            if ( objAttr.isEmpty() != true ) {
                robjResult.insert(clsModXML::mscszAttrs, objAttr);
            }
            robjResult.insert(clsModXML::mscszNode, robjElement.nodeName());
        
            if ( robjElement.hasChildNodes() == true ) {
            //Process any child nodes
                int intChildren = robjElement.childNodes().size();
                QDomNodeList lstChildNodes = robjElement.childNodes();
                for( int c=0; c<intChildren; c++ ) {
                    QDomElement objChildEl(lstChildNodes.item(c).toElement());
                    QJsonObject objJsonChild;
                    asTree(objChildEl, objJsonChild);
        
                    if ( objJsonChild.isEmpty() != true ) {
                        QJsonObject::const_iterator citChildren = robjResult.find(clsModXML::mscszChildren);
                        QJsonArray aryChildren;
        
                        if ( citChildren != robjResult.end() ) {
            //An array is already present get the array
                            aryChildren = citChildren->toArray();
                        }
            //Add the new chilren to the array
                        aryChildren.append(objJsonChild);
            //Update the result
                        robjResult.insert(clsModXML::mscszChildren, aryChildren);
                    }
                }
            }
        }
        

        My XML that I'm using to test:

        <?xml version="1.0" encoding="utf-8"?>
        <form title="Test form">
        	<simon>Hello World</simon>
        	<susan><!--
        	var Hello = 123;
        	// --></susan>
               <lewis><![CDATA[
        	alert("hello");
        	// ]]></lewis>
        	<entry label="First name:" cols="24" maxlength="24" accept="alpha_only" eol="true"/>
        	<entry label="Surnname:" cols="24" maxlength="24" accept="alpha_only" eol="true"/>
        	<entry label="Sex:" eol="true">
        		<option value="Male"/>
        		<option value="Female"/>
        	</entry>
        	<entry label="Address:" maxlength="256" accept="alpha_numeric" cols="56" rows="5" eol="true"/>
        </form>
        

        I would expect several different types to be encountered as the node simon contains just text, susan contains a comment and lewis contains script.

        Kind Regards,
        Sy

        JonBJ 1 Reply Last reply
        0
        • SPlattenS SPlatten

          @JonB , I am doing exactly that in my function, I've single stepped through the function and I don't see any type other than QDomNode::ElementNode.

          Here is my code:

          QDomElement objElement = objXML.documentElement();
          QJsonObject objResponse;
          asTree(objElement, objResponse);
          

          The asTree function is called recursively:

          void clsModXML::asTree(QDomElement& robjElement, QJsonObject& robjResult) {
              QDomNode::NodeType eNodeType = robjElement.nodeType();
          
              if ( eNodeType != QDomNode::ElementNode ) {
          //I have a breakpoint here and it never gets here!
                  return;
              }
              QDomNamedNodeMap mpAttr = robjElement.attributes();
              QJsonObject objAttr;
              for( int i=0; i<mpAttr.size(); i++ ) {
                  QDomNode item(mpAttr.item(i));
                  eNodeType = item.nodeType();
          
                  if ( eNodeType != QDomNode::AttributeNode ) {
                      continue;
                  }
                  objAttr.insert(item.nodeName(), item.nodeValue());
              }
              if ( objAttr.isEmpty() != true ) {
                  robjResult.insert(clsModXML::mscszAttrs, objAttr);
              }
              robjResult.insert(clsModXML::mscszNode, robjElement.nodeName());
          
              if ( robjElement.hasChildNodes() == true ) {
              //Process any child nodes
                  int intChildren = robjElement.childNodes().size();
                  QDomNodeList lstChildNodes = robjElement.childNodes();
                  for( int c=0; c<intChildren; c++ ) {
                      QDomElement objChildEl(lstChildNodes.item(c).toElement());
                      QJsonObject objJsonChild;
                      asTree(objChildEl, objJsonChild);
          
                      if ( objJsonChild.isEmpty() != true ) {
                          QJsonObject::const_iterator citChildren = robjResult.find(clsModXML::mscszChildren);
                          QJsonArray aryChildren;
          
                          if ( citChildren != robjResult.end() ) {
              //An array is already present get the array
                              aryChildren = citChildren->toArray();
                          }
              //Add the new chilren to the array
                          aryChildren.append(objJsonChild);
              //Update the result
                          robjResult.insert(clsModXML::mscszChildren, aryChildren);
                      }
                  }
              }
          }
          

          My XML that I'm using to test:

          <?xml version="1.0" encoding="utf-8"?>
          <form title="Test form">
          	<simon>Hello World</simon>
          	<susan><!--
          	var Hello = 123;
          	// --></susan>
                 <lewis><![CDATA[
          	alert("hello");
          	// ]]></lewis>
          	<entry label="First name:" cols="24" maxlength="24" accept="alpha_only" eol="true"/>
          	<entry label="Surnname:" cols="24" maxlength="24" accept="alpha_only" eol="true"/>
          	<entry label="Sex:" eol="true">
          		<option value="Male"/>
          		<option value="Female"/>
          	</entry>
          	<entry label="Address:" maxlength="256" accept="alpha_numeric" cols="56" rows="5" eol="true"/>
          </form>
          

          I would expect several different types to be encountered as the node simon contains just text, susan contains a comment and lewis contains script.

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

          @SPlatten
          That's why I wrote

          Note that for what you are doing you need to work from QDomNodes, not QDomElements.

          I'm not going to follow your code, but both of these look wrong to me:

          void clsModXML::asTree(QDomElement& robjElement
          QDomElement objChildEl(lstChildNodes.item(c).toElement());

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

          Converts a QDomNode into a QDomElement. If the node is not an element the returned object will be null.

          All QDomElements are QDomNodes, but not all QDomNodes are QDomElements, e.g. comments.

          Since you want to visit/deal with all node types, you will need to visit/deal with at QDomNode level.

          qDebug() << lstChildNodes.item(c).nodeType();
          qDebug() << lstChildNodes.item(c).isElement();    // this will be `false` for some nodes
          
          SPlattenS 2 Replies Last reply
          3
          • JonBJ JonB

            @SPlatten
            That's why I wrote

            Note that for what you are doing you need to work from QDomNodes, not QDomElements.

            I'm not going to follow your code, but both of these look wrong to me:

            void clsModXML::asTree(QDomElement& robjElement
            QDomElement objChildEl(lstChildNodes.item(c).toElement());

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

            Converts a QDomNode into a QDomElement. If the node is not an element the returned object will be null.

            All QDomElements are QDomNodes, but not all QDomNodes are QDomElements, e.g. comments.

            Since you want to visit/deal with all node types, you will need to visit/deal with at QDomNode level.

            qDebug() << lstChildNodes.item(c).nodeType();
            qDebug() << lstChildNodes.item(c).isElement();    // this will be `false` for some nodes
            
            SPlattenS Offline
            SPlattenS Offline
            SPlatten
            wrote on last edited by
            #5

            @JonB , thank you, I'll check it out.

            Kind Regards,
            Sy

            1 Reply Last reply
            0
            • JonBJ JonB

              @SPlatten
              That's why I wrote

              Note that for what you are doing you need to work from QDomNodes, not QDomElements.

              I'm not going to follow your code, but both of these look wrong to me:

              void clsModXML::asTree(QDomElement& robjElement
              QDomElement objChildEl(lstChildNodes.item(c).toElement());

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

              Converts a QDomNode into a QDomElement. If the node is not an element the returned object will be null.

              All QDomElements are QDomNodes, but not all QDomNodes are QDomElements, e.g. comments.

              Since you want to visit/deal with all node types, you will need to visit/deal with at QDomNode level.

              qDebug() << lstChildNodes.item(c).nodeType();
              qDebug() << lstChildNodes.item(c).isElement();    // this will be `false` for some nodes
              
              SPlattenS Offline
              SPlattenS Offline
              SPlatten
              wrote on last edited by
              #6

              @JonB , ok, done that...questions, again this is the sample XML:

              <?xml version="1.0" encoding="utf-8"?>
                  <form title="Test form">
              	<simon>
              		Hello World
              	</simon>
              	<susan><!--
              		var Hello = 123;
              		// -->
              	</susan>
              	<lewis><![CDATA[
              		alert("hello");
              		// ]]>
              	</lewis>
              	<entry label="First name:" cols="24" maxlength="24" accept="alpha_only" eol="true"/>
              	<entry label="Surnname:" cols="24" maxlength="24" accept="alpha_only" eol="true"/>
              	<entry label="Sex:" eol="true">
              		<option value="Male"/>
              		<option value="Female"/>
              	</entry>
              	<entry label="Address:" maxlength="256" accept="alpha_numeric" cols="56" rows="5" eol="true"/>
              </form>
              

              Why is the content of simon, susan and lewis of type BaseNode ?

              Kind Regards,
              Sy

              JonBJ 1 Reply Last reply
              0
              • SPlattenS SPlatten

                @JonB , ok, done that...questions, again this is the sample XML:

                <?xml version="1.0" encoding="utf-8"?>
                    <form title="Test form">
                	<simon>
                		Hello World
                	</simon>
                	<susan><!--
                		var Hello = 123;
                		// -->
                	</susan>
                	<lewis><![CDATA[
                		alert("hello");
                		// ]]>
                	</lewis>
                	<entry label="First name:" cols="24" maxlength="24" accept="alpha_only" eol="true"/>
                	<entry label="Surnname:" cols="24" maxlength="24" accept="alpha_only" eol="true"/>
                	<entry label="Sex:" eol="true">
                		<option value="Male"/>
                		<option value="Female"/>
                	</entry>
                	<entry label="Address:" maxlength="256" accept="alpha_numeric" cols="56" rows="5" eol="true"/>
                </form>
                

                Why is the content of simon, susan and lewis of type BaseNode ?

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

                @SPlatten
                I don't know, and I don't know whether that might depend on how you write your code. I think you have to look at e.g. susan's child nodes (not child elements) to meet the QDomNode::CommentNode?

                SPlattenS 1 Reply Last reply
                0
                • JonBJ JonB

                  @SPlatten
                  I don't know, and I don't know whether that might depend on how you write your code. I think you have to look at e.g. susan's child nodes (not child elements) to meet the QDomNode::CommentNode?

                  SPlattenS Offline
                  SPlattenS Offline
                  SPlatten
                  wrote on last edited by SPlatten
                  #8

                  @JonB, I don't get it either as far as I can see thats perfectly valid JavaScript in the susan node. But it gives the same type for all of those nodes.

                  Modified code:

                  void clsModXML::asTree(QDomNode& robjNode, QJsonObject& robjResult) {
                      QDomNode::NodeType eNodeType = robjNode.nodeType();
                  
                      if ( eNodeType != QDomNode::ElementNode ) {
                          return;
                      }
                      QDomNamedNodeMap mpAttr = robjNode.attributes();
                      QJsonObject objAttr;
                      for( int i=0; i<mpAttr.size(); i++ ) {
                          QDomNode item(mpAttr.item(i));
                          eNodeType = item.nodeType();
                  
                          if ( eNodeType == QDomNode::AttributeNode ) {
                              objAttr.insert(item.nodeName(), item.nodeValue());
                          }
                      }
                      if ( objAttr.isEmpty() != true ) {
                          robjResult.insert(clsModXML::mscszAttrs, objAttr);
                      }
                      robjResult.insert(clsModXML::mscszNode, robjNode.nodeName());
                  
                      if ( robjNode.hasChildNodes() == true ) {
                      //Process any child nodes
                          int intChildren = robjNode.childNodes().size();
                          QDomNodeList lstChildNodes = robjNode.childNodes();
                          for( int c=0; c<intChildren; c++ ) {
                              QDomNode objChildNode(lstChildNodes.item(c).toElement());
                              QJsonObject objJsonChild;
                              asTree(objChildNode, objJsonChild);
                  
                              if ( objJsonChild.isEmpty() != true ) {
                                  QJsonObject::const_iterator citChildren = robjResult.find(clsModXML::mscszChildren);
                                  QJsonArray aryChildren;
                  
                                  if ( citChildren != robjResult.end() ) {
                      //An array is already present get the array
                                      aryChildren = citChildren->toArray();
                                  }
                      //Add the new chilren to the array
                                  aryChildren.append(objJsonChild);
                      //Update the result
                                  robjResult.insert(clsModXML::mscszChildren, aryChildren);
                              }
                          }
                      }
                  }
                  
                  

                  Kind Regards,
                  Sy

                  JonBJ 1 Reply Last reply
                  0
                  • SPlattenS SPlatten

                    @JonB, I don't get it either as far as I can see thats perfectly valid JavaScript in the susan node. But it gives the same type for all of those nodes.

                    Modified code:

                    void clsModXML::asTree(QDomNode& robjNode, QJsonObject& robjResult) {
                        QDomNode::NodeType eNodeType = robjNode.nodeType();
                    
                        if ( eNodeType != QDomNode::ElementNode ) {
                            return;
                        }
                        QDomNamedNodeMap mpAttr = robjNode.attributes();
                        QJsonObject objAttr;
                        for( int i=0; i<mpAttr.size(); i++ ) {
                            QDomNode item(mpAttr.item(i));
                            eNodeType = item.nodeType();
                    
                            if ( eNodeType == QDomNode::AttributeNode ) {
                                objAttr.insert(item.nodeName(), item.nodeValue());
                            }
                        }
                        if ( objAttr.isEmpty() != true ) {
                            robjResult.insert(clsModXML::mscszAttrs, objAttr);
                        }
                        robjResult.insert(clsModXML::mscszNode, robjNode.nodeName());
                    
                        if ( robjNode.hasChildNodes() == true ) {
                        //Process any child nodes
                            int intChildren = robjNode.childNodes().size();
                            QDomNodeList lstChildNodes = robjNode.childNodes();
                            for( int c=0; c<intChildren; c++ ) {
                                QDomNode objChildNode(lstChildNodes.item(c).toElement());
                                QJsonObject objJsonChild;
                                asTree(objChildNode, objJsonChild);
                    
                                if ( objJsonChild.isEmpty() != true ) {
                                    QJsonObject::const_iterator citChildren = robjResult.find(clsModXML::mscszChildren);
                                    QJsonArray aryChildren;
                    
                                    if ( citChildren != robjResult.end() ) {
                        //An array is already present get the array
                                        aryChildren = citChildren->toArray();
                                    }
                        //Add the new chilren to the array
                                    aryChildren.append(objJsonChild);
                        //Update the result
                                    robjResult.insert(clsModXML::mscszChildren, aryChildren);
                                }
                            }
                        }
                    }
                    
                    
                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by
                    #9

                    @SPlatten said in QDomElement, how to get these?:

                    QDomNode objChildNode(lstChildNodes.item(c).toElement());

                    As I said earlier, what is this doing? I expect to see recursion on all child nodes, not just elements. No, I'm not following your logic, I'm just making an observation.

                    SPlattenS 1 Reply Last reply
                    2
                    • JonBJ JonB

                      @SPlatten said in QDomElement, how to get these?:

                      QDomNode objChildNode(lstChildNodes.item(c).toElement());

                      As I said earlier, what is this doing? I expect to see recursion on all child nodes, not just elements. No, I'm not following your logic, I'm just making an observation.

                      SPlattenS Offline
                      SPlattenS Offline
                      SPlatten
                      wrote on last edited by
                      #10

                      @JonB , well spotted, thank you!

                      Kind Regards,
                      Sy

                      1 Reply Last reply
                      1

                      • Login

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