web-dev-qa-db-ja.com

XPathで名前空間を無視する方法

私の目標は、XPathを使用して複数の名前空間を持つ複数のxmlファイルから特定のノードを抽出することです。名前空間URIを知っている限り、すべて正常に動作します。名前空間名自体は一定のままですが、スキーマ(XSD)はクライアントによって生成される場合があります。次に、基本的に3つの選択肢があります。

  1. 名前空間にスキーマを1つだけ使用して、何もうまくいかないことを望みます(確かですか?)

  2. 文書の子ノードを取得し、名前空間URIを持つ最初のノードを探し、そこに期待して、正しいURIを使用してURIを使用します。さまざまな理由でうまくいかない可能性があります

  3. どういうわけかxpathに伝える:「見て、名前空間を気にしない、この名前のすべてのノードを見つけてください。URIではなく名前空間の名前を伝えることさえできます」。そして、これはここの質問です...

これは、 here または here のような「名前空間認識に気付いていないので、私のxpath式が機能しない」という質問の繰り返しではありません。名前空間認識の使用方法を知っています。ただそれを取り除く方法ではありません。

93
kostja

local-name() XPath関数を使用できます。のようなノードを選択する代わりに

/path/to/x:somenode

すべてのノードを選択し、正しいローカル名を持つノードをフィルタリングできます。

/path/to/*[local-name() = 'somenode']
140
Dirk Vollmar

同じIn XPath2.をより簡潔な構文で実行できます。

/path/to/*:somenode

XmlTextReaderでNamespace = falseを使用できます

[TestMethod]
public void MyTestMethod()
{
    string _withXmlns = @"<?xml version=""1.0"" encoding=""utf-8""?>
<ParentTag xmlns=""http://anyNamespace.com"">
<Identification value=""ID123456"" />
</ParentTag>
";

    var xmlReader = new XmlTextReader(new MemoryStream(Encoding.Default.GetBytes(_withXmlns)));

    xmlReader.Namespaces = false;

    var content = XElement.Load(xmlReader);

    XElement elem = content.XPathSelectElement("/Identification");

    elem.Should().NotBeNull();
    elem.Attribute("value").Value.Should().Be("ID123456");
}

で:

using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
1

コメントすることは許可されていません(!!).

このハックには別の欠点があることがわかりました:文書がXML名前空間プレフィックスを宣言している場合は機能しません(コロンはXML名で有効ではなく、Namespaces == falseでは、読者はコロンを名前の一部として解釈します) 、例えば.

<ParentTag xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
xmlns="http://anyNamespace.com">
0
Dojo