XPath - 基于以下兄弟选择节点

zak*_*een 3 xpath qml

我有这样的查询:

/plist/dict[1]/dict/dict/dict/key/following-sibling::dict/string[string()='Algier']
Run Code Online (Sandbox Code Playgroud)

我真正想要选择的是'key'节点(就在下面的兄弟:: dict之前).

xml是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
    <dict>
    <key>en_GB</key>
            <dict>
                <key>Africa</key>
                <dict>
                    <key>Algeria</key>
                    <dict>
                        <key>60390</key>
                        <dict>
                            <key>NAME</key>
                            <string>Algier</string>
                            <key>LATITUDE</key>
                            <string>36.7500</string>
                            <key>LONGITUDE</key>
                            <string>3.0500</string>
                        </dict>
                        <key>60391</key>
                        <dict>
                            <key>NAME</key>
                            <string>Some other city</string>
                            <key>LATITUDE</key>
                            <string>36.7500</string>
                            <key>LONGITUDE</key>
                            <string>3.0500</string>
                        </dict>
                    </dict>
                </dict>
        </dict>
    </dict>
</plist>
Run Code Online (Sandbox Code Playgroud)

换句话说,我想在城市名称为'Algier'时选择'60390',或者在城市名称为'其他城市'时选择60391).

我在QML XmlListModel中这样做.

使用的更新代码 QML:

import QtQuick 1.0

Rectangle {
    id: container;
    width: 360
    height: 360

    function onLocationModelLoaded(){
        console.debug(weLocationModel.count);
    }

    XmlListModel{
        id: weLocationModel;
        source: "we_locations.plist";
        query: "/*/dict/dict/dict/dict/key[following-sibling::dict[1]/key[.='NAME' and following-sibling::string[1] = 'Algier']]"

        XmlRole{
            name: "cityId";
            query: "name()";
        }
        onStatusChanged: {
            if (status == XmlListModel.Ready){
                console.debug("Location Model Ready");
                container.onLocationModelLoaded();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

似乎嵌套的后续兄弟不起作用.例如:

query: "/*/dict/dict/dict/dict/key[following-sibling::dict[1]/key[.='NAME']]"
Run Code Online (Sandbox Code Playgroud)

这两个总是返回:

Error XPST0003 in file:///Users/Ali/qtprojects/welocationtest-build-simulator/welocationtest.app/Contents/MacOS/welocationtest, at line 2, column 97: syntax error, unexpected ], expecting )
Error XPST0003 in file:///Users/Ali/qtprojects/welocationtest-build-simulator/welocationtest.app/Contents/MacOS/welocationtest, at line 2, column 91: syntax error, unexpected ], expecting end of file
file:///Users/Ali/qtprojects/welocationtest-build-simulator/welocationtest.app/Contents/Resources/qml/welocationtest/main.qml:17:9: QML XmlRole: invalid query: "name()"
Location Model Ready
0
Run Code Online (Sandbox Code Playgroud)

可能QML不遵循XPath标准吗?该解决方案适用于所有其他路径编辑器.

Dim*_*hev 5

一个精确选择所需key元素的XPath表达式是:

   /*/dict/dict/dict/dict
     /key
        [following-sibling::dict[1]/key
                  [.='NAME'
                 and
                   following-sibling::string[1] = $pCity
                  ]
        ]
Run Code Online (Sandbox Code Playgroud)

当$ pCity设置/替换时"Algier",此XPath表达式选择:

<key>60390</key>
Run Code Online (Sandbox Code Playgroud)

当$ pCity设置/替换时"Some other city",此XPath表达式选择:

<key>60391</key>
Run Code Online (Sandbox Code Playgroud)

基于XSLT的验证:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:param name="pCity" select="'Some other city'"/>

 <xsl:template match="/">
  <xsl:copy-of select=
  "/*/dict/dict/dict/dict
     /key
        [following-sibling::dict[1]/key
                  [.='NAME'
                 and
                   following-sibling::string[1] = $pCity
                  ]
        ]
  "/>
 </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

对提供的XML文档应用此转换时:

<plist version="1.0">
    <dict>
        <key>en_GB</key>
        <dict>
            <key>Africa</key>
            <dict>
                <key>Algeria</key>
                <dict>
                    <key>60390</key>
                    <dict>
                        <key>NAME</key>
                        <string>Algier</string>
                        <key>LATITUDE</key>
                        <string>36.7500</string>
                        <key>LONGITUDE</key>
                        <string>3.0500</string>
                    </dict>
                    <key>60391</key>
                    <dict>
                        <key>NAME</key>
                        <string>Some other city</string>
                        <key>LATITUDE</key>
                        <string>36.7500</string>
                        <key>LONGITUDE</key>
                        <string>3.0500</string>
                    </dict>
                </dict>
            </dict>
        </dict>
    </dict>
</plist>
Run Code Online (Sandbox Code Playgroud)

产生了想要的正确结果:

<key>60391</key>
Run Code Online (Sandbox Code Playgroud)

在上述转换中我们替换:

 <xsl:param name="pCity" select="'Some other city'"/>
Run Code Online (Sandbox Code Playgroud)

:

 <xsl:param name="pCity" select="'Algier'"/>
Run Code Online (Sandbox Code Playgroud)

并再次应用转换,然后我们再次得到正确的结果:

<key>60390</key>
Run Code Online (Sandbox Code Playgroud)