XPathSelectElement始终返回null

Jea*_*erc 34 c# xml xpath

为什么这个Xpath无法使用XDocument.XPathSelectElement?

Xpath的:

//Plugin/UI[1]/PluginPageCategory[1]/Page[1]/Group[1]/CommandRef[2]
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

C#代码:

myXDocument.XPathSelectElement("//Plugin/UI[1]/PluginPageCategory[1]/Page[1]/Group[1]/CommandRef[2]", myXDocument.Root.CreateNavigator());
Run Code Online (Sandbox Code Playgroud)

Cum*_*yah 27

使用名称空间时,必须在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.
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

  • 什么可怕的代码.XML名称空间是非常丑陋的东西. (53认同)
  • 如果您必须显式添加前缀/ns 组合,那么从 XmlReader 加载 `NameTable` 有什么意义?我假设您这样做是因为您不知道文档用于所需命名空间的前缀。但是,这不也意味着没有必要用 `NameTable` 初始化 `XmlNamespaceManager` 吗? (2认同)

mdo*_*ghe 16

这应该是对@ 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 = ...;
Run Code Online (Sandbox Code Playgroud)

  • 只是想指出应该为默认命名空间加前缀的问题。即 namespaceManager.AddNamespace("","http://www.MyNamespace.ca/MyPath") 将使 DefaultNamespace 属性符合预期,但 XPathSelectElement 不会使用它。误导!!! (2认同)

小智 8

在您的情况下,最简单的方法是使用 XPath节点测试节点名称和位置来选择元素。您的 XPath 选择:

myXDocument.XPathSelectElement("//Plugin/UI[1]/PluginPageCategory[1]/Page[1]/Group[1]/CommandRef[2]", myXDocument.Root.CreateNavigator());
Run Code Online (Sandbox Code Playgroud)

可以很容易地翻译成:

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]");
Run Code Online (Sandbox Code Playgroud)

无需创建和传递 XmlNamespaceManager 作为参数。