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. Cannot read XSD attribute with QXMLStreamReader
QtWS25 Last Chance

Cannot read XSD attribute with QXMLStreamReader

Scheduled Pinned Locked Moved Unsolved General and Desktop
qxmlstreamreadexmlxsdparsing
4 Posts 2 Posters 884 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.
  • J Offline
    J Offline
    jepessen
    wrote on last edited by
    #1

    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?

    VRoninV 1 Reply Last reply
    0
    • J jepessen

      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?

      VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by
      #2

      @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
      1
      • VRoninV VRonin

        @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()

        J Offline
        J Offline
        jepessen
        wrote on last edited by
        #3

        @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
        0
        • VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by VRonin
          #4

          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
          1

          • Login

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