[Qt-interest] Why is using XmlPatterns so cumbersome?
Jason H
scorp1us at yahoo.com
Thu Mar 25 18:22:13 CET 2010
I was reading: http://qt.nokia.com/developer/qtquarterly/checking-the-weather-with-xquery
And I have seen this time and time again, and it keeps me from using the XmlPatterns stuff.
1. All the examples/documentation seem to work with static files ("doc("somefile.xml")"). Nothing uses "live" data off the web, or a QString or QByteArray that I already have. The 2nd example in the documentation for QXmlQuery::bindVariable(const QXmlName, QIODevice) shows setQuery then bindVariable, but the comments later say the proper way is the bind then set like in the 1st example.
2. XPath isn't ever covered.
3. There is no way to search and replace in XML using XQuery/XPath.
I was hoping to see an example that takes a QUrl, gets it from the web (local content is so 1990), and runs it through the XPath/XQuery stuff.
In .Net, this is done much more simply. There is one class that is the XML document, then there is a Navigator class that attaches to that document (or any node of a document), that allows XPath queries.
In.Net:
m_provideMsgNav = doc->CreateNavigator();
m_provideNSMgr = gcnew XmlNamespaceManager( m_provideMsgNav->NameTable);
nodes = m_provideMsgNav->Select("/Some/Xpath/Expression", m_provideNSMgr);
while (nodes->MoveNext())
{
... // I can edit nodes here
}
To put it in Qt terms I wish to have:
QXmlNavigator nav (&doc);
QList<QDomNode> list = nav.findNode("/Some/Xpath/Expression");
foreach (QDomNode n, list)
{
...// and I can edit nodes here.
}
Also, it is a shortcoming that QDomNodeList can't be directly used with foreach()
This is because I work with XML and Qt every day. I get XML files and I have the responsibility to add/update only the portion of the document I am allowed to update. I want the QtXml and QXmlPatterns modules merged (functionally, I realize that binary compatibility would be broken so I am not asking for a true merge), because there is no way to use both concurrently. What I mean by that is, I cannot use XPath to find nodes, then modify the document using the XPath-found nodes.
Ideally, QDomNode would take an XPath expression and return a QList<QDomNode> This would make searching and modifying the documents easy, as you could use a nested foreach() structure to handle your document processing. Imagine the following:
foreach (QDomNode n1, doc.xpath('Element/SubElement"))
{
n1.setAttibute("lastUpdate", QDateTime::currentDateTime().toString(Qt::ISODate));
foreach (QDomNode n2, doc.xpath('SubSubElement[@color='blue']"))
{
n2.setAttibute("color", "red")
}
}
Right now, the only way do this is to use QDomNode::firstChildElelement(), nextSiblingElement(), and lastChildElement() and then you have to compare each element's attributes on your own. And what's more is you can't do the Element/SubElement jump. Of course the .Net stuff allows this. But in Qt documents are read-only, or QDomDocument if you need read-write. There's no way to really search and replace in an XML document. The XQuery trick only gives you a new document, that you can't use to modify the original.QWebElement comes close, but that requires a GUI and WebKit, and only support CSS2 selectors.
If we take this back to the weather example, and assume we have XPath merged with QDomNode, and the XML weather data is in doc,
QMap<QDateTime, QPair<QString, QString> > data;
foreach (QDomNode timeItem doc.query("weatherdata/forecast/tabular/time"))
{
QDomElement timeElement = timeItem.toElement();
QDateTime time = QDateTime::fromString(timeElement.attribute("from"));
QString temp =timeElement.query("temperature[@value]").toAttr().value();
QString units= timeElement.query("temperature[@unit]").toAttr().value();
data[time]=QPair(temp, units);
}
Which is a whole heck of a lot easier than writing a QAbstractXmlReceiver subclass.
More information about the Qt-interest-old
mailing list