Don't assume that the last step of the XPath is an element name
authorJan Arve Saether <jan-arve.saether@digia.com>
Thu, 4 Jul 2013 10:14:44 +0000 (12:14 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Tue, 9 Jul 2013 08:25:34 +0000 (10:25 +0200)
In order to find the number of items in the model, the model did a
second query on the document representing the result set.
So, suppose the user queried for //a/b/c, the result set would contain
all the 'c' elements from the input document.
In order to find the number of items in the result set, it did a second
query with the expression  "count(/dummy:items/c)", where 'c' was
extracted from the last step in the original XPath expression

For simple expressions, this worked fine.

However, if the last step had a predicate such as "//c/parent::b" it
didn't work.

The solution is to not filter *again* the last step when we query for
the count, since we know that all result items are direct children of
"dummy:items", and instead just execute the query
"count(dummy::items/*)".

This should also potentially improve performance.

Task-number: QTBUG-17588
Change-Id: Ib2fdf1ec8b91022df0597e089ad34d34b04428b0
Reviewed-by: Alan Alpert <aalpert@blackberry.com>
src/imports/xmllistmodel/qqmlxmllistmodel.cpp
tests/auto/quick/qquickxmllistmodel/data/groups.qml [new file with mode: 0644]
tests/auto/quick/qquickxmllistmodel/data/groups.xml [new file with mode: 0644]
tests/auto/quick/qquickxmllistmodel/qquickxmllistmodel.pro
tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp

index 856c063..7cc4e64 100644 (file)
@@ -388,8 +388,7 @@ void QQuickXmlQueryEngine::doQueryJob(XmlQueryJob *currentJob, QQuickXmlQueryRes
     b.open(QIODevice::ReadOnly);
 
     QString namespaces = QLatin1String("declare namespace dummy=\"http://qtsotware.com/dummy\";\n") + currentJob->namespaces;
-    QString prefix = QLatin1String("doc($inputDocument)/dummy:items") +
-                     currentJob->query.mid(currentJob->query.lastIndexOf(QLatin1Char('/')));
+    QString prefix = QLatin1String("doc($inputDocument)/dummy:items/*");
 
     //figure out how many items we are dealing with
     int count = -1;
diff --git a/tests/auto/quick/qquickxmllistmodel/data/groups.qml b/tests/auto/quick/qquickxmllistmodel/data/groups.qml
new file mode 100644 (file)
index 0000000..c1b574a
--- /dev/null
@@ -0,0 +1,10 @@
+import QtQuick 2.0
+import QtQuick.XmlListModel 2.0
+
+XmlListModel {
+    source: "groups.xml"
+    query: "//animal[@name='Garfield']/parent::group"
+
+    XmlRole { name: "id"; query: "@id/string()" }
+    XmlRole { name: "name"; query: "@name/string()" }
+}
diff --git a/tests/auto/quick/qquickxmllistmodel/data/groups.xml b/tests/auto/quick/qquickxmllistmodel/data/groups.xml
new file mode 100644 (file)
index 0000000..5de4d2e
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<groups version="2.0">
+    <group id="1" name="Animals" type="root">
+        <group id="11" name="dogs">
+            <animal id="111" name="Lassie"/>
+            <animal id="112" name="Laika"/>
+            <animal id="113" name="Wile E. Coyote" type="fictional"/>
+        </group>
+        <group id="12" name="cats">
+            <animal id="121" name="Garfield" type="fictional"/>
+            <animal id="122" name="Sylvester" type="fictional"/>
+        </group>
+        <group id="13" name="birds">
+            <animal id="131" name="Donald Duck" type="fictional"/>
+            <animal id="132" name="Phoenix" type="fictional"/>
+        </group>
+    </group>
+</groups>
index 047d8ca..9172a22 100644 (file)
@@ -12,3 +12,6 @@ CONFIG += parallel_test
 
 QT += core-private gui-private v8-private qml-private network testlib xmlpatterns
 DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
+
+OTHER_FILES += \
+    data/groups.qml
index 847cc50..1f7a802 100644 (file)
@@ -101,6 +101,7 @@ private slots:
     void threading();
     void threading_data();
     void propertyChanges();
+    void selectAncestor();
 
     void roleCrash();
 
@@ -964,6 +965,18 @@ void tst_qquickxmllistmodel::propertyChanges()
     delete model;
 }
 
+void tst_qquickxmllistmodel::selectAncestor()
+{
+    QQmlComponent component(&engine, testFileUrl("groups.qml"));
+    QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
+    QVERIFY(model != 0);
+    QTRY_COMPARE(model->rowCount(), 1);
+
+    QModelIndex index = model->index(0, 0);
+    QCOMPARE(model->data(index, Qt::UserRole).toInt(), 12);
+    QCOMPARE(model->data(index, Qt::UserRole+1).toString(), QLatin1String("cats"));
+}
+
 void tst_qquickxmllistmodel::roleCrash()
 {
     // don't crash