Cannot read XSD attribute with QXMLStreamReader
-
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 QXMLStreamReadervoid 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 withattributes()
the list is empty (in the codex
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?
-
@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 callingm_node.attributes()
. What I suspect is happening is that in the real code you are moving the cursor beyond theStartElement
before callingm_node.attributes()
-
@VRonin this is almost the real code I don't call
readNextStartElement
orreadNextElement
anywhere else in the function, so I' trying to retrieve attributes whenm_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; }
-
I'm sorry but you must be moving the cursor in some way. Try putting
Q_ASSERT(m_node.isStartElement());
just beforeauto 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; }