web-dev-qa-db-ja.com

XPathSelectElementは常にnullを返します

XDocument.XPathSelectElementを使用してこのXpathが機能しないのはなぜですか?

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());
34

名前空間を使用する場合は、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.

お役に立てれば。

27
Cumbayah

これはおそらく@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 = ...;
17
mdonoughe

あなたのケースで最も簡単な方法は、XPath axesnode testをノード名と位置に使用して要素を選択することです。 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を作成してパラメーターとして渡す必要はありません。

6
Yannis Stereo