我有一个XML文件(它是一个iTunes文件),其中包含以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Major Version</key><integer>1</integer>
<key>Minor Version</key><integer>1</integer>
<key>Application Version</key><string>12.3.3.17</string>
...
<key>Music Folder</key><string>file://localhost/C:/Users/username/longpath/</string>
</dict>
</plist>
如何获取最后一个字符串的值,<key>
是'音乐文件夹'?
这是一个非常大的文件,所以我宁愿不遍历所有节点。
我尝试了以下一些方法:
XmlNode location = xmlDocument.SelectSingleNode("descendant::dict[key='Music Folder']");
location = xmlDocument.SelectSingleNode("//text()[.='Music Folder']");
location = xmlDocument.SelectSingleNode("string[last()]");
location = xmlDocument.SelectSingleNode("dict::string[last()]");
location = xmlDocument.SelectSingleNode("descendant::dict[string[last()]]");
我对XPath表达式并不熟悉并且无法正确表达。
我也对LINQ解决方案持开放态度。
答案 0 :(得分:2)
使用17毫秒来获取文档中最后一个节点的值。为了测试速度,我创建了一个包含Music Folder
节点作为最后key
节点的文档,以及示例中列出的前3个节点大约11000次。
string ReadValue(XDocument xDoc, string key)
{
var node = xDoc.Element("plist")
.Element("dict")
.Elements("key")
.Single(e => e.Value == key)
.NextNode as XElement;
return node.Value;
}
答案 1 :(得分:2)
文档的XPath表达式在文档根目录的上下文中进行评估,因此您需要理想地指定plist
节点,并且我假设您需要字符串值,因此您需要导航到该节点。
XmlNode location = xmlDocument.SelectSingleNode("plist/dict/key[.='Music Folder']/following-sibling::string[1]")
请注意,该值不是嵌套在key元素中,而是以下兄弟。鉴于这最终会出现,你可能会逃脱:
XmlNode location = xmlDocument.SelectSingleNode("plist/dict/string[last()]")
我会在XPath中明确指定plist
节点,因为它将可能的匹配保持在最小值。需要注意的另一点是,您的XPath可能会最终使用底层技术迭代每个节点,具体取决于您如何构造表达式,因为某些实现可能能够应用优化。
你很接近,但我发现你正在混淆运营商并使用::
或[]
/
更合适。 ::
将轴与节点名分隔开,因此descendants::dict
获取名为dict
的上下文节点(xmlDocument)的所有后代。 /
运算符实际上是child::
的简写。 []
是缩放结果集的过滤谓词。