c++xmlqtqxmlstreamreader

QT Reading XML file, structure


I am using QXmlStreamReader to process an XML file. The read loop is quite straight forward:

    if ( !file.open(QFile::ReadOnly | QFile::Text) ) {
        strErrors.append(mcszConfigFile);
        strErrors.append("\n\nDoes not exists!\n\n");
    }
    xmlrdr.setDevice(&file);
    xmlrdr.readNext();
    blnRootFound = false;
    while( !xmlrdr.atEnd() ) {
        /* [Edit] This shouldn't be here! if ( xmlrdr.isStartElement() ) */{
            QXmlStreamAttributes attrs = xmlrdr.attributes();
            QStringRef srfNodeName = xmlrdr.name();
            bool blnEndElement = xmlrdr.isEndElement();
            bool blnStartElement = xmlrdr.isStartElement();
            bool blnInvalid = true;

            if ( attrs.length() > 0 ) {
                QString strID, strNodeName = srfNodeName.toString();

                if ( attrs.hasAttribute(mcszXMLattrID) == false ) {
                    strErrors.append("Node: ");
                    strErrors.append(qPrintable(srfNodeName.toString()));
                    strErrors.append("Has no id!\n");
                    break;
                }
                strID = attrs.value(mcszXMLattrID).toString();

                if ( strNodeName.compare(mcszXMLnodeRoot) == 0 ) {
                    blnRootFound = true;
                    blnInvalid = false;
                    mstrRootID = strID;
                } else if ( strNodeName.compare(mcszXMLnodeButton) == 0
                         || strNodeName.compare(mcszXMLnodeButtonBar) == 0
                         || strNodeName.compare(mcszXMLnodeOption) == 0 ) {
                    blnInvalid = false;
                } else if ( strNodeName.compare(mcszXMLnodeControl) == 0 ) {
                    for( int t=0; mcpszValidControlTypes[t]!=NULL; t++ ) {
                        if ( strID.compare(mcpszValidControlTypes[t]) == 0 ) {
                            blnInvalid = false;
                            break;
                        }
                    }
                }
                if ( strID.length() > 0 && blnInvalid == false ) {
                    clsXMLnode objNode = clsXMLnode(strNodeName, &attrs, this);                    
                    msmapNodes.insert(std::pair<QString, clsXMLnode>(strID, objNode));
                    msmapAreas.insert(std::pair<QString, QRect>(strID, objNode.rctGetGeom()));
                    if ( blnStartElement == true ) {

                    }
                }
            }
        }
        xmlrdr.readNext();
    }
    if ( file.isOpen()  ) {
        file.close();
    }

The XML that I am reading:

    <?xml version="1.0" encoding="utf-8"?>
    <!--
     Node:          gui
     Attrbuttes:    left, right, top and bottom defines the pixel white space to allow
                    from the edge of the display
            language, should be set to the appropriate country code, an XML file named using
            the country code must exist, e.g. 44.xml
    //-->
    <gui id="root" bottom="0" left="0" right="0" top="24" language="44">
      <control id="trainstrip"
           x="(center:SCREEN) - (25%:SCREEN_WIDTH)" y="(top:SCREEN)" height="40px" width="(50%:SCREEN_WIDTH)"/>
      <control id="elevationstrip"
               x="(left:trainstrip) - 56px" y="(top:trainstrip) + (height:trainstrip) + 24px" width="56px" height="{75%:SCREEN_HEIGHT}"/>
      <control id="lofmimics"
           color_arc="#ffaaaaaa"
               color_axis="#fff0000"
               color_bg="#ffaaaaaa"
               color_needle="#ffffff00"
               color_min_limit="#ffbbbb00"
               color_max_limit="#ffcc00cc"
               color_port="#ff00aa00"
               color_starboard="'#ffaa0000"
               elevation_height="275px"
           elevation_mech_max="85"
               elevation_mech_min="-10"
               elevation_max="85"
               elevation_margin_left="64px"
               elevation_margin_bottom="64px"
               elevation_min="-10"
               elevation_pensize_limit="3"
               elevation_pensize_reading="3"
               elevation_width="[elevation_height]"
               elevation_x="0px"
           elevation_y="0px"
               training_mech_starboard="170"
               training_mech_port="-170"
               training_pensize_port="5"
               training_pensize_starboard="5"
               training_pensize_limit="3"
               training_pensize_reading="3"
               training_starboard="150"
               training_port="-150"
               training_width="(left:elevationstrip)"
               training_height="([training_width])"
           training_x="([elevation_x])"
           training_y="([elevation_height])"
               x="(left:SCREEN)"
           width="([x]:elevationstrip)"
           height="([training_height]) + ([elevation_height])"
               y="(bottom:SCREEN) - ([height])"/>
      <buttonbar id="modes"      
             height="50%"
             width="100px"
             x="(RIGHT:SCREEN) - ([width])"
             y="(TOP:SCREEN)"
             title="MODE"
             color_bg="#ffaaaaaa"
             border="inset:#ffcccccc,#ff333333"
             button_height="24px"
                 button_width="80px"
             vertical_space="4px">
        <button id="btnsetup" color_bg="#ff3399ff" x="0px" y="{top:modes}">
          <option value="0" text="operate<"/>
          <option value="1" text="setup"/>
          <option value="2" text="install"/>
          <option value="3" text="startup"/>
          <option value="4" text="shutdown"/>
        </button>     
      </buttonbar>
    </gui>

The issue I'm having is that the flags blnEndElement and blnStartElement do not appear to accurately reflect the correct states when reading the file, blnEndElement is always false and blnStartElement is always true.

What I want to do is build up the node/element hierarchy whilst reading and processing the XML.


Solution

  • The issue I'm having is that the flags blnEndElement and blnStartElement do not appear to accurately reflect the correct states when reading the file, blnEndElement is always false and blnStartElement is always true.

    If I understand your issue correctly, you are getting wrong values for local variables blnEndElement and blnStartElement. I highlight below the if condition which is the cause for this behavior:

      while( !xmlrdr.atEnd() ) {
            if ( xmlrdr.isStartElement() ) {
            //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                QXmlStreamAttributes attrs = xmlrdr.attributes();
                QStringRef srfNodeName = xmlrdr.name();
                bool blnEndElement = xmlrdr.isEndElement();  
                bool blnStartElement = xmlrdr.isStartElement(); 
                //   ^^^^^^^^^^ Same as above if condition, ALWAYS be TRUE, if control reaches this line.
    
                bool blnInvalid = true;
    

    The internal code is executed only when if condition is satisfied else code will be skipped.