2011-10-27 22 views
5

私はすべての古いコードを元に戻し、最適化しようとしています。私は最近、偶然見つけ、それは私が困惑得ているものは、このためのXPath解決策を見つけることを試みている:属性に基づいて特定の要素を見つける

function findit($search) { 
    $i=0; 
    foreach($xml as $page) { //loop to find specific $element based on $attribute 
     if($page['src']==$search) { return $i; } 
     $i++; 
    } 
} 

は、それが後のXMLの要素を参照するために使用することができるように$iを返す必要があります。

これは可能なはずですが、動作するように見えるxpath文字列がいくつか見つかりましたが、そうではありません。彼らは通常、preceding-childrenを参照して、xpath()関数を介してそれらを数えますが、元のソースをもう見つけられず、それをPHP xpath文字列に変換する方法がありません。

これも可能ですか?それとも、それは私がすでに持っているものよりも優れている/速い/効率的ですか?提案/解決策?

EDIT:私の現在のPHP関数でTanduのソリューションについては

私のXMLファイルの例

<range> 
    <page src="attribute1" /> 
    <page src="attribute2" /> 
    etc... 
    <page src="attribut20" /> 
</range> 

$iは常に0を返しますがで発見されているものの位置$search返す必要があります。編集して、simplexmlを変換する必要がなくなりました。

function findit($search) { 
    $dom=new DOMDocument('1.0'); 
    $dom->load($file); 
    $xpath=new DOMXPath($dom); 
    $i=$xpath->evaluate("count(/range/page[@src='$search']/preceding-sibling::*)"); 
    die($dom->saveXML()); 
} 

答えて

3

PHPは、XPathを処理するための少なくとも2つ(私の知っていること)のメソッドがあります。独自のxpath()メソッドを持つDOMXPathDOMDocumentで動作し、ライブラリ、およびSimpleXMLを、。実際の式を評価する場合(例ではiを取得するなど)、DOMXPath::evaluate()を使用する必要があります。 SimpleXML::xpath()は唯一の意志DOMXPath::query()として(ノードリストを返します。そこPHPのxpath_方法もあるが、これらは他の方法の機能のバージョンも、まだDOMコンテキストノードのオブジェクトを必要とするように見える。

私はわからないんだけど上記のあなたの例ではxmlはあるが、以下の例では、DOMXPathを使うことの最大を使用しています。私の知る限り、DOMDocumentSimpleXMLを変換する簡単な方法がない。あなただけ別途XMLをロードする必要があります。

$xml = <<<XML 
    <root> 
     <child attribute="one" /> 
     <child attribute="one" /> 
     <child attribute="one" /> 
     <child attribute="one" /> 
     <child attribute="one" /> 
     <child attribute="two" /> 
     <child attribute="one" /> 
     <child attribute="one" /> 
     <child attribute="one" /> 
     <child attribute="one" /> 
     <child attribute="one" /> 
    </root> 
XML; 
$dom = new DOMDocument; 
$dom->loadXML($xml); 
//DOMXPath requires DOMDocument in its constructor 
$xpath = new DOMXPath($dom); 
//evaluate will return types .. we are expecting an int, not a DOMNodeList 
//Look for a child node of root named "child" with attribute="two" 
//Count all its preceding siblings. 
$i = $xpath->evaluate('count(/root/child[@attribute="two"]/preceding-sibling::*)'); 
+0

関係者限り、私は彼の兄のDOM忘れのためのSimpleXMLを使用して! – mseancole

+0

*入力が次の行に移動する代わりにコメントを追加することを認識していませんでしたXD 私のXMLは、もちろん、simplexmlです。これは私が持っているものですが、最もエレガントな方法であるかどうかはわかりませんが、まだ動作させることができません:( ここで正しくフォーマットできなかったのでオリジナルのポストにコードを追加しました:( – mseancole

+0

@showerheadできますあなたのXMLを参照してください "ルート"と "子"はノード名です。たとえば、あなたが ''を代わりに使用している場合、私の例では "root"を "father"と "child"を "son"に置き換えます。私はあなたの質問の例で "子供"を使っているのを見ています。 –

0

使用単一のXPath式であるため、結果を反復処理する必要はありません

elementWithSomeName[@attribute = 'someNeededValue'] 

または(場合には、「属性は、要素の名前です):

elementWithSomeName[attribute = 'someNeededValue'] 
+0

はい、私はこれまでに、xmlの特定の位置を見つけることができるように繰り返しました。ありがとう、結構です – mseancole

関連する問題