2011-08-14 7 views
13

XML文書内のいくつかのノードには名前空間があり、定義された接頭辞で指定されます。名前空間修飾ノードのXPath構文がないのはなぜですか?

XPath 1.0にローカル名()を指定して名前空間を無視することは可能です。

しかし、私は、XPathのライターが完全な名前空間修飾名を識別子として使用してノードを見つけることを可能にしたいと考えています。

呼び出すコード(私の場合はJava)に名前空間宣言を追加することをお勧めします。しかし、これはXpathを書く人が名前空間で作業する能力を持っていないことを意味します!

純粋なXPathを使用して完全修飾名でノードを見つけるにはどうすればよいですか?

+2

私が質問を正しく理解している場合、なぜ 'addNamespace(" abc "、" http://example.com ")のような命令を使って名前空間を宣言する必要があるのか​​を尋ねてきます。 'http:// example.com'を何らかの形でクエリの中で直接使用するのではなく、'/abc:node'のようなXpathクエリです。私は質問を正しく解釈しましたか? –

+1

@ジョンボールはい、そうです。何らかの形でXPath内でabc = http://example.comを宣言した後に、XPathクエリで接頭辞abcを直接使用するとよいでしょう。私はXPath式が短く、その中に定義を挿入するのは普通ではないが、技術的にはXPathでそれができないようにすることは技術的に何もないことを理解しています。 –

+1

良い質問、+1。接頭辞はわずかな構文砂糖であると考えられているので、名前空間URIは重要な意味を持ちますが、接頭辞を混乱させることなくノード名を照合することは有益でしょう。プレフィックスを宣言する方法はありません。 – LarsH

答えて

13

"識別子として"あなたが何を意味しているか分かりません。

純粋なXPathを使用して完全修飾名でノードを見つけるにはどうすればよいですか?

XPath 1.0では、local-name()とnamespace-uri()を使用することで、

"*[local-name() = 'foo' and namespace-uri() = 'http://my.org/ns/2.0']" 

XPath 2.0では、名前空間に関連するより豊富な機能があります。 namespace-uri-from-QName()。しかし、私は彼らがあなたが望むものについて上記で改善するかどうかはわかりません。

+1

いいですね。ちょっと不器用です - 私はむしろhttp://my.org/ns/2.0|fooのようなものを、これらの関数名なしで書いたいと思います。接頭辞をどうにか使って、JavaではなくXPathで宣言するのも良いですが要件を満たしている。 –

+1

"完全な名前空間修飾名を識別子として使用する"というのは、namespace + local-nameを使用してノードを正確に参照できなければならないということです。あなたの答えはどのように表示されます。 –

+0

@ JoshuaFox:XPath自体で接頭辞を宣言できることは非常に便利だと思います。 「彼ら」がXPathにそれを含めないことを決めた理由はいくつかあると思いますが、回避策が非常に冗長であるため、大きなギャップのように見えます。 – LarsH

1

XPathクエリ中に名前空間を使用します。 Javaでは、完全修飾された名前空間ではなく、それらのクエリでプレフィックスを使用したい場合は、NamespaceContextの実装が必要です。 NamespaceContextのインスタンスをXPathに追加してください。標準のJDK実装を使用すると仮定しますが、その概念はJaxenなどにも当てはまります。

次に、//customns:Elementなどのクエリを実行できます。

そうでないか(何らかの理由で)NamespaceContextを使用できない場合には、唯一の解決策はlocal-namenamespace-uriの機能を使用しているように見える:

Document doc = ...; 
XPath xp = XPathFactory.newInstance().newXPath(); 
String name = "Element"; 
String ns = "http://www.custom.org/#"; 
String expr = "//*[local-name() = '"+name+" and namespace-uri() = '"+ns+"']"; 
Node node = ((NodeList)xp.evaluate(expr, doc, XPathConstants.NODESET)).item(0); 
+1

ありがとうございました。プレフィックスではなく、完全な名前空間名を使用したい場合はどうすればよいですか?つまり、何かのように。 Javaで名前空間を宣言するのを避けることはできますか?私の目標は、外部ソースからXPath式を読み込むことです。そのため、これを個別に指定する必要はありません。 –

+0

これは、ソースの見た目にもよります。つまり、// abc:Elementと名前空間宣言がない場合、理論上はスタックされています.abcが指しているものを知る方法はありません。しかし、それらの外部式があなたの作業ドキュメントと同じプレフィックスを持つことを絶対に確信できれば、ドキュメント内の対応する名前空間を検索し、NamespaceContextを構築するか、まったく使用しないことができます。私はそれを行う方法を概説した私の答えを更新します。 – emboss

+0

残念ながら、local-name()とnamespace-uri()の組み合わせよりも[他の解決策はありません](http://www.jguru.com/forums/view.jsp?EID=1073634)ようです。 – emboss

4

作業で現在のXPath 3.0、名前空間uriを直接指定できるようにするために、URI qualified QNamesのリテラル式が含まれます。ここで

EQNamesのいくつかの例は以下のとおりです。

  • パイは、名前空間接頭辞なしの字句のQNameです。
  • math:piは、名前空間プレフィックスを持つ字句QNameです。
  • "http://www.w3.org/2005/xpath-functions/math":piはURILiteralを使って名前空間URIを指定します。それは字句のQNameではありません。

私はSaxon 9.3は、Java APIを介して使用可能でなければならないのXPath 3.0のプレビュー実装が含まれてだと思います。

+3

現在、3.0フィーチャーは製品のコマーシャル版でのみ有効になっていますが、正しいです。 「なぜこの機能は以前のバージョンではなかったのか」という質問は、誰もそれを提案しなかったか、十分に力を出していないか、同じ問題を解決するためにライバルの提案と競争しなければならなかった。 –

0

のXPath 3.0の仕様は言う:

Q{http://www.w3.org/2005/xpath-functions/math}pi 

はこれが存在し-DBで例えばこの瞬間(2015年10月)で働いています。

+0

@ e4c5:XMLは、リテラル構文のものにURIを使用するのが好きです。答えをもっと慎重に読んでください。 –

+0

@ NathanTuggyはい、あなたは正しいですが、それはリンクのみの回答として表示されました(このコメントはシステムによって自動挿入されています)。私はそのコメントを削除しました。 – e4c5

関連する問題