XPathSelectElement总是返回null
为什么这个Xpath不能使用XDocument.XPathSelectElement?XPathSelectElement总是返回null
的Xpath:
//Plugin/UI[1]/PluginPageCategory[1]/Page[1]/Group[1]/CommandRef[2]
XML
<Plugin xmlns="http://www.MyNamespace.ca/MyPath">
<UI>
<PluginPageCategory>
<Page>
<Group>
<CommandRef>
<Images>
</Images>
</CommandRef>
<CommandRef>
<Images>
</Images>
</CommandRef>
</Group>
</Page>
</PluginPageCategory>
</UI>
</Plugin>
C#代码:
myXDocument.XPathSelectElement("//Plugin/UI[1]/PluginPageCategory[1]/Page[1]/Group[1]/CommandRef[2]", myXDocument.Root.CreateNavigator());
当使用的命名空间,这些都必须在XPath查询也可使用。您的XPath查询仅适用于没有名称空间的元素(可以通过从XML中删除名称空间进行验证)。
这里是你展示如何创建和传递一个命名空间管理器的示例:
var xml = ... XML from your post ...;
var xmlReader = XmlReader.Create(new StringReader(xml)); // Or whatever your source is, of course.
var myXDocument = XDocument.Load(xmlReader);
var namespaceManager = new XmlNamespaceManager(xmlReader.NameTable); // We now have a namespace manager that knows of the namespaces used in your document.
namespaceManager.AddNamespace("prefix", "http://www.MyNamespace.ca/MyPath"); // We add an explicit prefix mapping for our query.
var result = myXDocument.XPathSelectElement(
"//prefix:Plugin/prefix:UI[1]/prefix:PluginPageCategory[1]/prefix:Page[1]/prefix:Group[1]/prefix:CommandRef[2]",
namespaceManager
); // We use that prefix against the elements in the query.
Console.WriteLine(result); // <CommandRef ...> element is printed.
希望这有助于。
什么可怕的代码。 XML命名空间是真正难看的东西。 – 2011-11-14 06:34:46
如果您必须明确地添加前缀/ ns组合,那么从XmlReader加载NameTable的意义何在?我假设你这样做是因为你不知道文档用于所需名称空间的前缀。但是,这不就意味着没有必要用'NameTable'初始化'XmlNamespaceManager'吗? – crush 2018-02-28 19:51:15
有一种方法可以在不改变xpath的情况下做到这一点。我找到的解决方案是在将XML解析到XDocument时删除名称空间。
这里是个例:
var regex = @"(xmlns:?[^=]*=[""][^""]*[""])";
var myXDocument = XDocument.Parse(Regex.Replace("MyXmlContent", regex, "", RegexOptions.IgnoreCase | RegexOptions.Multiline))
现在的命名空间没有了,这是easyer操纵。
_“现在名称空间不见了”_您可能没有一个格式良好的XML文档... – 2011-04-29 04:47:06
香肠工厂解决方案。 – 2011-04-29 06:21:18
呃...它对我来说非常适合。请注意,当您无法更改xpath时它可能很有用。 – 2011-04-29 13:48:46
这应该可能是对@ Cumbayah的帖子的评论,但我似乎无法留下任何评论。
你可能更喜欢使用这样的东西,而不是使用XmlReader来获取名称表。
var xml = ... XML from your post ...;
var myXDocument = XDocument.Parse(xml);
var namespaceManager = new XmlNamespaceManager(new NameTable());
namespaceManager.AddNamespace("prefix", "http://www.MyNamespace.ca/MyPath");
var result = ...;
只是想指出缺省名称空间应加前缀的问题。即namespaceManager.AddNamespace(“”,“http://www.MyNamespace.ca/MyPath”)将使DefaultNamespace属性与预期一致,但它不会被XPathSelectElement使用。误导! – 2012-08-21 12:52:06
你的情况最简单的方法是使用XPath 轴和节点测试节点名称和位置选择的元素。 您的XPath的选择:
myXDocument.XPathSelectElement("//Plugin/UI[1]/PluginPageCategory[1]/Page[1]/Group[1]/CommandRef[2]", myXDocument.Root.CreateNavigator());
可以很容易地转换成:
myXDocument.XPathSelectElement("/child::node()[local-name()='Plugin']/child::node()[local-name()='UI'][position()=1]/child::node()[local-name()='PluginPageCategory'][position()=1]/child::node()[local-name()='Page'][position()=1]/child::node()[local-name()='Group'][position()=1]/child::node()[local-name()='CommandRef'][position()=2]");
没有必要创建和传递的XmlNamespaceManager作为参数。
太棒了,这个作品很棒。命名空间应该很简单,但非常棘手,所以这个解决方案非常有用。 – 2017-05-24 02:34:16
xpath查询中没有名称空间信息,这可能是原因。试着缩小这个范围,删除XML上的命名空间,看看是否会得到你的结果? – Cumbayah 2011-04-28 13:30:14
这可能是由于命名空间 - 检查从XML中删除它是否修复它,如果有,请创建一个NamespaceManager。 – 2011-04-28 13:31:17
@Cumbayah:打我吧! – 2011-04-28 13:32:11