qtkmlqtxml

How can I use Qt's QXmlQuery to run XPath queries on a local file?


I'm trying to grab the coordinates from .kml files that look something like this:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.0">
    <Document>
        <name>Name</name><Style id="roadStyle"><LineStyle><color>7fcf0064</color><width>6</width></LineStyle></Style><Snippet><![CDATA[<font size=+1><a href="http://example.com/">Printable view</a></font>]]></Snippet>
        <Placemark>
            <name>Example</name>
            <description><![CDATA[example]]></description><address>100 Example St</address><StyleMap><Pair><key>normal</key><Style><IconStyle><Icon><href>http://example.com</href></Icon><hotSpot x="0.000000" y="0.000000" xunits="fraction" yunits="fraction" /></IconStyle><ListStyle><ItemIcon><href>http://example.com</href></ItemIcon></ListStyle></Style></Pair><Pair><key>highlight</key><Style><IconStyle><scale>1.000000</scale><Icon><href>http://example.com</href></Icon><hotSpot x="0.000000" y="0.000000" xunits="fraction" yunits="fraction" /></IconStyle><ListStyle><ItemIcon><href>http://example.com</href></ItemIcon></ListStyle></Style></Pair></StyleMap><Point><coordinates>0.000000,0.000000,0</coordinates></Point><LookAt><longitude>0.000000</longitude><latitude>0.000000</latitude><range>100.000000</range><tilt>45.000000</tilt><heading>0.000000</heading></LookAt>
        </Placemark>
        <Placemark>
            <name>Route</name>
            <description><![CDATA[Example]]></description>
            <GeometryCollection>
                <LineString>
                    <coordinates>0.000000,0.000000,0.000000 0.000000,0.000000,0.000000 0.000000,0.000000,0.000000 0.000000,0.000000,0.000000 0.000000,0.000000,0.000000 0.000000,0.000000,0.000000 0.000000,0.000000,0.000000</coordinates>
                </LineString>
            </GeometryCollection>
            <styleUrl>#roadStyle</styleUrl>
        </Placemark>
    </Document>
</kml>

I'm trying to use QXmlQuery to retrieve the coordinates with an XPath string similar to this:

kml/Document/Placemark[last()]/GeometryCollection/LineString/coordinates

I've tested that here and confirmed it works, so far so good. But I've had a horrible time getting it to work in Qt. I've tried a lot of things, including suggestions in other posts here on SO, without luck. Here's a couple examples showing the variations:

void testQuery1(QString &filename) {
    QXmlQuery query;
    query.bindVariable("kmlFile", QVariant(filename));
    query.setQuery("declare default element namespace \"http://earth.google.com/kml/2.0\"; declare variable $kmlFile external; doc($kmlFile)//coordinates");

    QStringList results;
    query.evaluateTo(&results);

    qDebug() << results.size();
}

void testQuery2(QString &filename) {
    QFile file(filename);
    file.open(QIODevice::ReadOnly);

    QXmlQuery query;
    query.setFocus(&file);
    query.setQuery("kml/Document/Placemark[last()]/GeometryCollection/LineString/coordinates");

    QString result;
    query.evaluateTo(&result);

    qDebug() << result;
}

I get 0 and " \n" from each of those, respectively. Where am I going wrong here and what do I need to do to fix it? I'm open to other approaches as long as they stay within Qt (I'm using 4.7) and standard C++.


Solution

  • After much experimentation, I seem to have hit upon the magic recipe:

    void testQuery(QString &filename) {
        QFile file(filename);
        file.open(QIODevice::ReadOnly);
    
        QXmlQuery query;
        query.bindVariable("kmlFile", &file);
        query.setQuery("declare default element namespace \"http://earth.google.com/kml/2.0\"; declare variable $kmlFile external; doc($kmlFile)/kml/Document/Placemark[last()]/GeometryCollection/LineString/coordinates/text()");
    
        QString result;
        query.evaluateTo(&result);
    
        qDebug() << result;
    
        file.close();
    }
    

    That gives me my string of zeroes (or whatever the coordinates may be).