I've been trying to fetch node text values from this XML file:
<!DOCTYPE structure>
<data>
<x>
<id>1</id>
<nam>tytuł</nam>
<tab>21</tab>
<ind>5</ind>
<pre>TY</pre>
<khw>C.TY</khw>
</x>
<x>
<id>2</id>
<nam>autor</nam>
<tab>21</tab>
<ind>5</ind>
<pre>FO</pre>
<khw>C.FO</khw>
</x>
<x>
<id>3</id>
<nam>hasło korporatywne</nam>
<tab>21</tab>
<ind>5</ind>
<pre>FN</pre>
<khw>C.FN</khw>
</x>
</data>
What I want to do is to fetch every node and it's children and convert it to QMap. I have no trouble with fetching single element, but when it comes to fetch children items by setting result of QXmlQuery as a focus, the QString that i evaluate the child node query is empty. I use this piece of code:
QXmlResultItems results;
QFile structure("./structure.xml"); // xml file, as described earlier
structure.open(QFile::ReadOnly);
QXmlQuery query;
query.setFocus(&structure);
query.setQuery("data/x");
query.evaluateTo(&results);
QXmlItem next = results.next();
while(!next.isNull()) {
qDebug() << next.toNodeModelIndex().stringValue(); // everything's fine. It prints contents of <x>'s child nodes
QXmlQuery childQuery;
QString r;
childQuery.setFocus(next);
childQuery.setQuery("./nam/text()"); // already tested: "/nam/text()", "/nam/string()", "x/nam/string()", "data/x/nam/string()" etc... still no luck.
childQuery.evaluateTo(&r);
qDebug() << r; // prints \n but it should print content of <nam> node.
next = results.next();
}
Software I use: Qt 4.7.2 SDK directly from Qt website, QtCreator 2.3.1 on Windows and Linux (without any difference in this particular case, results are the same). I want to be sure that's the problem of my lack of knowledge, rather than software bug, please help
Unfortunately, it is unclear from Qt Documentation that in cases when you want to use QXmlQuery::setFocus(const QXmlItem& item)
overload in order to query child nodes, you should create corresponding QXmlQuery
objects using QXmlQuery(const QXmlNamePool& np)
constructor to make them share the same QXmlNamePool
object. Such sharing, simply speaking, relates queries to each other.
Considering this, your example should look like following:
QFile structure("./structure.xml");
structure.open(QFile::ReadOnly);
QXmlQuery query;
query.setFocus(&structure);
query.setQuery("data/x");
QXmlResultItems results;
query.evaluateTo(&results);
QXmlQuery childQuery(query.namePool());
while (!results.next().isNull()) {
childQuery.setFocus(results.current());
childQuery.setQuery("nam/text()");
QString r;
childQuery.evaluateTo(&r);
qDebug() << r;
}
Moreover, you can go further and reuse initial QXmlQuery
object:
QFile structure("./structure.xml");
structure.open(QFile::ReadOnly);
QXmlQuery query;
query.setFocus(&structure);
query.setQuery("data/x");
QXmlResultItems results;
query.evaluateTo(&results);
while (!results.next().isNull()) {
query.setFocus(results.current());
query.setQuery("nam/text()");
QString r;
query.evaluateTo(&r);
qDebug() << r;
}
Instead of using evaluateTo( QString * )
use the QStringList
version. It should work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With