2009-05-21 17 views
9

の最初の結果を選択して、私はこの質問を見てきました:Select first instance only with XPath?XPathの

しかし、私はノードセットのようにしている場合:


<container value=""> 
    <data id="1"></data> 
    <data id="2">test</data> 
    <container> 
    <data id="1">test</data> 
    <data id="3">test</data> 
    </container> 
</container> 

を今私のシナリオは、このノードセットが深いということです文書の中には、内部のコンテナへのポインタがあります。だから、私はXPathに "/ container/container"という接頭辞を付けなければなりません(実際にはパスは長くなりますが、この例ではそうするべきです)。

EDIT: 私が必要とするのは、idが1の「データ」ノードです。このノードは、最初に最も低いノードまたは最も近い祖先から来る必要があります。だから、もし私が "現在"(/コンテナ/コンテナ)でそれを見つけることができないなら、私は先祖を見て、最も近いものを得るべきです(あるいは最後に何も見つけられません)。私はこれを試してみました:

/コンテナ/コンテナ/祖先-または自己::コンテナ/データ[ID @ = "1"] 2ノードとの結果セットを戻します

。私は最後の()を使って最深のものを得ることができると思ったので、最後にそれをつけましたが、無駄にしました。

+0

仕様がより明瞭で行うことができました。データノードが必要ですか?データノードのIDは1ですか?データノードのIDが1でない場合は元のコンテナを作成し、ドキュメントを親コンテナに移動して、IDが1のデータノードがあるかどうかを確認します。 1が見つかりました。それはそれを記述していますか? – AnthonyWJones

+0

私は少し鮮明に見ていたものを説明しようとしましたが、いくつかはそれを推測しました。ごめんなさい! –

答えて

5

どのように(最後の仮止めてみました)上の?私は、これは動作するはずだと思う:

/container/container/ancestor-or-self::container/data[@id="1"][last()] 

EDIT:

右、もちろん、私は括弧を忘れてしまった:

(/container/container/ancestor-or-self::container/data[@id="1"])[last()] 

他の回答の一つとして、これが同じになり、どの;オリジナルポスターが指摘するようにしかし、この式は上の失敗:

のstackoverflowの精神に忠実
<container value=""> 
    <container> 
    <data id="1">a3</data> 
    <data id="3">a4</data> 
    </container> 
    <data id="1">a1</data> 
    <data id="2">a2</data> 
</container> 

、しかし私は他の回答の一つで私の答えを組み合わせて、すべてのケースで動作何かを得ることができます。

(/container/container/ancestor-or-self::container[data[@id="1"]])[last()]/data[@id="1"] 

ちなみに、1つのコンテナの複数の@did-is-1 <のデータの子がある場合、これはすべてを返します。代わりに

@id="1" 

(/container/container/ancestor-or-self::container[data[@id="1"]])[last()]/data[@id="1"][1] 
+0

希望の結果をここで読みましたが正しい場合(大きい場合)、last()が先祖または両方のブランチで一致するため、実際の問題であるため、結果セットを早い段階でクリップするか、遅い段階でクリップする必要があります(Daveのように)。 – annakata

+0

これはこれを行います。ありがとう(誰も)! –

1

私はあなたが求めているものを100%明確でないんだけど、私は、これは右読めば、多分あなただけ欲しい:

/container/container/ancestor-or-self::container[1]/data[@id='1'] 

ノート「[1]」

編集:それについて考え、もう少し、以下、これまで右が= $ N

/container/container/ancestor-or-self::container[data[@id=$N]][1]/data[@id=$N] 

かなり極端なxpathing @ IDを探しているすべてのケースのために私のために動作します。基本的には、祖先からのノードセットが位置1にある最下位を返します。それはあなたが望むものですが、ノードにも興味のあるデータノードがあるという第2の条件を付ける必要があります。これらの条件が満たされると、実際のデータにさらにトンネルするだけの適切なノードが得られます。あなたは離れてそれを取ると、アルゴリズムと考えるとxpathが容易になる時間の

99%:)

+0

私はそれを試みましたが、すべてのケースをカバーしていません。 @ id = '2'の代わりに探していたらどうなりますか?先祖の前にある現在のノードの結果を優先したいが、後退できるようにする。 –

+0

編集を参照してください:リストされているすべてのケースをカバーしていると信じています – annakata

0

あなたは試してみました:のみ最初な<データ>要素を返すに

position() == 1 
+0

position()== 1の場合は、ancestor-or-self :: allを一緒に削除するだけです。私は、要件は最初のデータノードではなく、IDが1のデータノードであると考えています。問題はできるだけ明確ではありません。 – AnthonyWJones

11

last()が正しくスコープされていることを確認します。試してみてください:

同様
(/container/container/ancestor-or-self::container/data[@id="1"])[last()] 

//container[last()] 

と:

(//container)[last()] 

は同じものではありません。最初は、階層の各レベルで最後のコンテナノードを返します - 複数の一致 - そして最後のコンテナノードが見つかりました - 一致する1つを返します。

+0

ああ、これはうまくいった!ありがとうございました。 –

+0

実際には、一致するデータ要素の前に子コンテナノードが指定されている場合、これは機能しません。 –

+0

@Nick Spacek - 私は以下の答えで改善しました。 –

0

は [位置()= 1]

EXを試みます。

/容器/コンテナ/先祖又は自己::コンテナ/データ【位置()= 1]