一般来说,我是 XPath 和 xml 解析的新手。我阅读了一些文档,但找不到解决我的问题的方法。我的 .xml 看起来像这样(仅供引用:它是“iTunes Music Library.xml”的播放列表部分):
<dict>
<array>
<dict>
<key>Name</key><string>Playlist 1</string>
<key>Playlist ID</key><integer>187826</integer>
<key>Playlist Persistent ID</key><string>04250E0617138909</string>
<key>All Items</key><true/>
<key>Playlist Items</key>
<array>
<dict>
<key>Track ID</key><integer>11111</integer>
</dict>
<dict>
<key>Track ID</key><integer>22222</integer>
</dict>
</array
</dict>
<dict>
<key>Name</key><string>Playlist 2</string>
<key>Playlist ID</key><integer>187826</integer>
<key>Playlist Persistent ID</key><string>04250E0617138909</string>
<key>All Items</key><true/>
<key>Playlist Items</key>
<array>
<dict>
<key>Track ID</key><integer>23456</integer>
</dict>
<dict>
<key>Track ID</key><integer>34567</integer>
</dict>
</array
</dict>
</dict>
我的输入是一个包含播放列表名称的字符串。现在这是我想要的输出:与该特定播放列表相关的所有歌曲 ID。不幸的是,名称不是例如数组或第一个字典的属性。这是我得到的(java代码):
ap.selectXPath("//dict/array/dict/string[1][text()=\"" + playlistName + "\"]");
当然,这只是给了我我的播放列表名称。那么从现在开始如何进行呢?我想到了:像这样解析文件,直到解析器达到所需的名称:
ap.selectXPath("//dict/array/dict[" + count++ +"]/string[1]");
带有“整数计数”。然后使用适当的查询从该位置重新开始。再说一次,这似乎并不优雅或高效。
长话短说:是否有 XPath 查询可以满足我的要求?
最佳答案
一路一个dict
以 plist 格式工作的元素是交替的元素对,每个值都是其 key
的第一个后续兄弟元素.因此,对于给定的键,您可以将值访问为
key[. = 'Entry name']/following-sibling::*[1]
因此,对于您感兴趣的特定示例,
dict
“播放列表 1”的元素是/dict/array/dict[key[. = 'Name']/following-sibling::*[1] = 'Playlist 1']
其轨道列表
array
是/dict/array/dict[key[. = 'Name']/following-sibling::*[1] = 'Playlist 1']
/key[. = 'Playlist Items']/following-sibling::*[1]
然后是
integer
的集合给出轨道 ID 的元素将是/dict/array/dict[key[. = 'Name']/following-sibling::*[1] = 'Playlist 1']
/key[. = 'Playlist Items']/following-sibling::*[1]
/dict/key[. = 'Track ID']/following-sibling::*[1]
如果您从用户输入中获取播放列表名称并且它们可能包含单引号或双引号字符,请务必小心。您没有说您使用的是什么库,但如果它支持定义变量,那么您应该使用该机制来注入(inject)您的值,而不是依赖字符串连接来构建您的表达式。
关于xml - 棘手的 xpath 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17975398/