2011-01-07 9 views
2

次の操作を実行するためにXPathクエリ文字列を把握しようとしています。私は<region>内に含まれていない<data>すべてのノードをつかむしたい'レベル'で反復するXPathクエリ

<root> 
    <data>foo1</data> 
    <irrelevant-node> 
     <data>foo1</data> 
    </irrelevant-node> 
    <irrelevant-node /> 
    <data>foo2</data> 
    <irrelevant-node /> 
    <region> 
     <data>bar1</data> 
     <data>bar2</data> 
     <irrelevant-node /> 
     <region> 
      <data>hello1</data> 
      <irrelevant-node /> 
      <data>hello2</data> 
      <region> 
       <irrelevant-node /> 
       <data>world1</data> 
      </region> 
     </region> 
     <irrelevant-node /> 
     <data>bar3</data> 
     <irrelevant-node> 
      <data>foo1</data> 
     </irrelevant-node> 
     <irrelevant-node /> 
    </region> 
    <irrelevant-node /> 
</root> 

は、このようなXML文書を考えます。

次に、最上位のノード<region>をすべて取得し、それらのノード上で前のプロセスを繰り返して、相対的に動作させたいと思います。

本質的には、<data>ノード上でその内容に基づいていくつかのプロセス(PHP)を実行して、それらを置き換えるつもりです。しかし、<region>ノードは一種のスコープ区切り文字として機能し、指定されたスコープ内のすべての<data>ノードを処理すると、リージョン・レベルを下げます。 <data>ノードは、他の無関係なノード内にネストすることができます。

XPathがこれに最適なツールであるかどうかは不明ですが、これを整理しようとすると多くの問題があります。前述の通り、私はDOMクラスのPHP実装を使用しています。

+0

/bar/region/irrelevant-node/dataは、2番目の繰り返しで "bar ..." 'data'を選択する必要がありますか? –

+0

** @アレハンドロ**:それは正しいです。最初の反復ではすべての 'foo'データを取得する必要があります。第2の「バー」。第3の「こんにちは」など。 – Dan

+0

良い質問、+1。説明と解決方法については私の答えを見てください。 :) –

答えて

3

基本的に、私は は、それらを置き換え、その 内容に基づいてノード上のプロセスの数(PHP) を実行するつもりです。 しかし、ノードはスコープ区切り文字の のソートとして機能し、 スコープ内のすべての<data>ノードを処理し終えると、私はリージョンレベルを下げます。 <data>ノードは、 の他の無関係なノード内にネストすることができます。

使用$nは0、1、...、MAX-深さである

//data[count(ancestor::region) = $n] 

$ nのすべての値に対して、式はすべて「レベル$ n」のdata要素をに選択します。

あなたによって選択されたノードの各々についてcount(ancestor::region)+1の最大としてを「最大深さ」を見つけることができる:

//region[not(descendant::region)] 

この最大が単一のXPath 2.0式でを指定することができますが含まれますが、単一のXPath 1.0式では使用できません。

+0

ありがとうございました** Dimitre Novatchev **;私はそれにショットを与えます:) – Dan

+0

うーん、それは動作していないようです。無効な式であることを示します。私は '' zuq:data [count(ancestor :: zuq:region = 0)] 'をテストしました(対象ノードが' zuq'名前空間にあるとは言いませんでした)。 – Dan

+0

申し訳ありませんが、それはあなたと私のタイプミスのコレクションでした:)優秀!もう一度ありがとうございます** Dimitre **! – Dan