2011-10-27 11 views
5

Wracam do poprzedniego kodu i staram się go zoptymalizować. Coś mi niedawno natknął i że ma zdobyć mnie zakłopotany próbuje znaleźć rozwiązanie dla tego xpath:Znajdź określony element oparty na atrybucie

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

Musi powrócić $i tak, że może on być stosowany jako odniesienie do elementu w pliku XML później.

Wygląda na to, że powinno być możliwe, i znalazłem kilka łańcuchów xpath, które wyglądają tak, jakby powinny działać, ale nie. Zwykle odnoszą się do preceding-children i liczą je poprzez funkcję xpath(), ale nie mogę już znaleźć oryginalnych źródeł i nie tłumaczę tego na ciąg PHP xpath.

Czy to możliwe? Czy jest to lepsze/szybsze/wydajniejsze niż to, co już mam? Sugestie/rozwiązania?

EDIT: Dla Tandu za rozwiązanie

przykładzie mojego pliku XML

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

W mojej obecnej funkcji PHP, $i zawsze zwraca 0 ale powinien wrócić cokolwiek pozycja $search znajduje się przy ul. Edytowane, więc nie trzeba już konwertować 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()); 
} 

Odpowiedz

3

PHP ma co najmniej dwa (które znam) sposoby postępowania XPath: biblioteka DOMXPath, który współpracuje z DOMDocument i SimpleXML, który ma swoją własną metodę xpath(). Jeśli chcesz przetestować rzeczywiste wyrażenia (takie jak pobranie i w twoim przykładzie), musisz użyć DOMXPath::evaluate(). SimpleXML::xpath() tylko zwraca listę węzłów (jak DOMXPath::query(). Istnieją również xpath_ metody w PHP, ale te wydają się być funkcjonalne wersje innych metod i nadal wymagają DOM obiektów węzła kontekstowego.

Nie jestem pewien, co xml w przykładzie powyżej, ale poniższy przykład używa DOMXPath. z tego co wiem, nie istnieje prosty sposób przekonwertować SimpleXML do DOMDocument. musisz po prostu załadować xml oddzielnie.

$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

używa SimpleXML tak długo zapomniałem o jego starszy brat DOM! – mseancole

+0

* Nie zrealizowałem enter, aby dodać komentarz zamiast przejść do następnej linii XD Mój XML to oczywiście simplexml. To jest to, co mam, nie jestem pewien, czy jest to najbardziej elegancki sposób, ale nadal nie mogę go uruchomić :( Dodany kod w oryginalnym wpisie, ponieważ nie mogłem go poprawnie sformatować :( – mseancole

+0

@showerhead can I zobacz swój xml? Zauważ, że "root" i "child" są nazwami węzłów.Na przykład, jeśli masz ' ' zamiast tego, w moim przykładzie zamienić "root" na "ojciec" i "dziecko" na "syn". Widzę, że nadal używasz słowa "dziecko" w przykładzie w pytaniu. –

0

Wykorzystanie jedno wyrażenie XPath, więc nie trzeba powtarzać wyniku:

elementWithSomeName[@attribute = 'someNeededValue'] 

lub (w przypadku „atrybut jest nazwą elementu):

elementWithSomeName[attribute = 'someNeededValue'] 
+0

Tak, dotarłem aż tak daleko, byłem iteracji tak, że mogłem znaleźć jego określonej pozycji w xml, a więc $ i. Ale dziękuję – mseancole

Powiązane problemy