Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Unsolved Cannot read XSD attribute with QXMLStreamReader

    General and Desktop
    qxmlstreamreade xml xsd parsing
    2
    4
    412
    Loading More Posts
    • 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.
    • J
      jepessen last edited by

      I need to parse the following XSD:

      <?xml version="1.0" encoding="UTF-8"?>
      <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
        <xs:element name = "elementName">
          <xs:simpleType>
            <xs:restriction base = "xs:string">
            </xs:restriction>
          </xs:simpleType>
        </xs:element>
      </xs:schema>
      

      During the parsing I arrive to the restriction element. This is the code (rearranged) for parsing this element, that uses QXMLStreamReader

      void String::getFromBase() const {
        QXMLStreamReader m_node; // in true code it's a class member already initialized
        m_node.readNextStartElement();
        auto name = stripNamespace(m_node.name().toString()); // convert xs:restriction to restriction
        if (name != restriction) {
          throw Exception("Restriction is not found when reading string data");
        }
        bool hasBase{false};
        auto x = m_node.attributes().size(); // x is zero but it should be one
        for (const auto& it : m_node.attributes()) {
          auto attrName = stripNamespace(it.name().toString());
          if (attrName == "base") {
            hasBase = true;
            break;
          }
        }
        if (!hasBase) {
          throw Exception("Restriction needs 'base' attribute");
        }
        auto attribute = stripNamespace(m_node.attributes().value(BaseLabel).toString());
        if (attribute == "string") {
          int i = 0;
        }
      }
      

      When I run the code, the variable name is "restriction", so I arrive to the right position in the XML. But then when I retrieve attributes with attributes() the list is empty (in the code x is equal to zero) do I don't enter in the loop for cycling all attributes.

      What I'm doing wrong and what should I do for retrieving attributes of the node?

      VRonin 1 Reply Last reply Reply Quote 0
      • VRonin
        VRonin @jepessen last edited by

        @jepessen said in Cannot read XSD attribute with QXMLStreamReader:

        (rearranged)

        I think this is the key. To be able to read the attributes m_node.isStartElement() must return true just before calling m_node.attributes(). What I suspect is happening is that in the real code you are moving the cursor beyond the StartElement before calling m_node.attributes()

        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
        ~Napoleon Bonaparte

        On a crusade to banish setIndexWidget() from the holy land of Qt

        J 1 Reply Last reply Reply Quote 1
        • J
          jepessen @VRonin last edited by

          @VRonin this is almost the real code I don't call readNextStartElement or readNextElement anywhere else in the function, so I' trying to retrieve attributes when m_node.name() is "restriction".

          This is the actual real code (A bit incomplete because I'm focusin on this issue):

          Tree::String::Ptr String::getFromBase() const {
            auto parsedNode = make_shared<Tree::String>();
            m_node.readNextStartElement();
            auto name = stripNamespace(m_node.name().toString());
            if (name != RestrictionLabel) {
              throw Exception("Restriction is not found when reading string data");
            }
            auto x = m_node.attributes().size();
            bool hasBase{ false };
            for (const auto& it : m_node.attributes()) {
              auto attrName = stripNamespace(it.name().toString());
              if (attrName == BaseLabel) {
                hasBase = true;
                break;
              }
            }
            if (!hasBase) {
              throw Exception("Restriction needs 'base' attribute");
            }
            auto attribute = stripNamespace(m_node.attributes().value(BaseLabel).toString());
            if (attribute == StringLabel) {
              int i = 0;
            }
            return parsedNode;
          }
          
          1 Reply Last reply Reply Quote 0
          • VRonin
            VRonin last edited by VRonin

            I'm sorry but you must be moving the cursor in some way. Try putting Q_ASSERT(m_node.isStartElement()); just before auto x = m_node.attributes().size();

            This example parses the XSD you provided correctly (I also let QXmlStreamReader handle namespaces instead of having to write custom code for it):

            int main()
            {
                const QString xmlText(R"***(<?xml version="1.0" encoding="UTF-8"?>
                <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
                  <xs:element name = "elementName">
                    <xs:simpleType>
                      <xs:restriction base = "xs:string">
                      </xs:restriction>
                    </xs:simpleType>
                  </xs:element>
                </xs:schema>)***"
                );
                QXmlStreamReader reader(xmlText);
                while (!reader.atEnd()) {
                    switch(reader.readNext()){
                    case QXmlStreamReader::StartDocument:
                        qDebug("Start of document");
                        break;
                    case QXmlStreamReader::EndDocument:
                        qDebug("End of document");
                        break;
                    case QXmlStreamReader::StartElement:{
                        qDebug() << "Started Element: " << reader.name();
                        const auto attr = reader.attributes();
                        qDebug() << "Number of Attributes: " << attr.size() << " Attributes:";
                        for(auto&& att : attr)
                            qDebug() << att.name() << " = " << att.value();
                    }
                        break;
                    case QXmlStreamReader::EndElement:
                        qDebug() << "Finished Element: " << reader.name();
                        break;
                    default:
                        break;
                    }
                }
                return 0;
            }
            

            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
            ~Napoleon Bonaparte

            On a crusade to banish setIndexWidget() from the holy land of Qt

            1 Reply Last reply Reply Quote 1
            • First post
              Last post