XPath は、(意図的に) XML ドキュメントにしか存在しないいくつかの不明な名前空間に対して同じ XPath 式を使用する場合のために設計されていません。名前空間を事前に把握し、名前空間を XPath プロセッサに宣言し、その名前を式で使用する必要があります。Martin と Dan による回答は、C# でこれを行う方法を示しています。
この問題の理由は、XML 名前空間の仕様で最もよく表されています。
単一の XML ドキュメントに、複数のソフトウェア モジュールで定義および使用される要素と属性 (ここでは「マークアップ ボキャブラリ」と呼ぶ) を含めることができる、拡張マークアップ言語 (XML) のアプリケーションを想定しています。これの動機の 1 つはモジュール性です。そのようなマークアップ語彙が十分に理解されており、有用なソフトウェアが利用可能である場合、このマークアップを再発明するよりも再利用する方がよいでしょう。
複数のマークアップ語彙を含むこのようなドキュメントは、認識と衝突の問題を引き起こします。ソフトウェアモジュールは、他のソフトウェアパッケージ用のマークアップが同じ要素名または属性名を使用するときに発生する「衝突」に直面しても、処理するように設計されている要素と属性を認識できる必要があります。
これらの考慮事項により、異なるマークアップ語彙の名前間の衝突を回避するように、ドキュメント構成要素に名前を作成する必要があります。この仕様では、拡張された名前を要素と属性に割り当てることによってこれを実現するメカニズムである XML 名前空間について説明します。
つまり、名前空間は、ドキュメントが何について話しているのかを確実に把握するために使用されることになっています。その<head>
要素は、XHTML ドキュメントのプリアンブルについて話しているのでしょうか、それとも AnatomyML ドキュメントの誰かの頭について話しているのでしょうか? 名前空間にとらわれないように「想定」されることは決してありません。名前空間は、XML ボキャブラリで最初に定義する必要があります。
やりたいことはできるはずですが、単一の XPath 式ではできないと思います。まず最初に、ドキュメントを調べてすべての名前空間 URI を抽出し、次にこれらを名前空間マネージャーに追加して、必要な実際の XPath 式を実行する必要があります (この時点で、ドキュメント内の名前空間の分布について何かを知る必要があります)。ポイント、または実行する式がたくさんあります)。おそらく、XPath 以外のもの (DOM や SAX のような API) を使用して名前空間 URI を見つけるのが最善だと思いますが、XPath 名前空間軸 (XPath 1.0 の場合) を探索し、namespace-uri-from-QName
関数 (XPath 2.0の場合) を使用することもできます。またはオレグのような表現を使用する"configuration/*[local-name() = 'MyNode']"
. とにかく、最善の策は、名前空間にとらわれない XPath を書くことを避けることだと思います! 名前空間を事前に知らないのはなぜですか? 一致させるつもりのないものを一致させないようにするにはどうすればよいでしょうか。
編集 - 名前空間URIを知っていますか?
したがって、あなたの質問は私たち全員を混乱させたことがわかりました。名前空間の URI はわかっているようですが、XML ドキュメントで使用されている名前空間のプレフィックスはわかりません。実際、この場合、名前空間プレフィックスは使用されず、URI はそれが定義されているデフォルトの名前空間になります。知っておくべき重要なことは、選択したプレフィックス (またはプレフィックスの欠如) は、XPath 式 (および一般的な XML 解析) とは無関係であるということです。prefix / xmlns 属性は、ドキュメントがテキストとして表現されている場合に、ノードを名前空間 URI に関連付ける 1 つの方法にすぎません。この回答をご覧になることをお勧めします。ここでは、名前空間のプレフィックスを明確にしようとしています。
パーサーが考えるのと同じ方法で XML 文書を考えるようにしてください。各ノードには名前空間 URI とローカル名があります。名前空間プレフィックス/継承ルールにより、URI を何度も入力する手間が省けます。これを書き留める 1 つの方法は、Clark 表記法です。つまり、{ http://www.example.com/namespace/example }LocalNodeName と書きますが、この表記法は通常、ドキュメントに使用されるだけで、XPath はこの表記法について何も知りません。
代わりに、XPath は独自の名前空間プレフィックスを使用します/ns1:root/ns2:node
。しかし、これらは元の XML ドキュメントで使用される可能性のある接頭辞とはまったく別のものであり、何の関係もありません。どの XPath 実装にも、独自のプレフィックスを名前空間 URI にマップする方法があります。C# の実装では を使用しXmlNamespaceManager
、Perl ではハッシュを提供し、xmllint はコマンド ライン引数を取ります...したがって、必要なことは、既知の名前空間 URI の任意のプレフィックスを作成し、このプレフィックスを XPath 式で使用することだけです。使用するプレフィックスは問題ではありません。XML では、URI と localName の組み合わせに注意するだけです。
もう 1 つ覚えておくべきこと (驚くことがよくあります) は、XPath は名前空間の継承を行わないことです。名前空間が継承によるものか、xmlns 属性によるものか、名前空間プレフィックスによるものかに関係なく、名前空間を持つすべてのものにプレフィックスを追加する必要があります。また、常に URI と localNames の観点から考える必要がありますが、XML ドキュメントからプレフィックスにアクセスする方法もあります。これらを使用する必要があることはまれです。