2016-04-25 13 views
0

Ich versuche eine xpath-Abfrage auf das Ergebnis einer früheren Xpath-Abfrage durchzuführen. Ich kann die xpath-Abfrage schreiben, um die untergeordneten Elemente zu extrahieren, und dann über die resultierenden Elemente iterieren und sie an eine andere Funktion zur weiteren Verarbeitung übergeben. Meine Probleme treten auf, wenn ich jedes dieser resultierenden Elemente mit einem weiteren XPath anwenden möchte.PHP XPath auf das Ergebnis eines XPath mit entweder DOMDocument oder SimpleXML

die XML Bei

<grandfather> 
    <mother> 
     <son>1</son> 
     <son>2</son> 
    </mother> 
    <mother> 
     <daughter>3</daughter> 
    </mother> 
    <mother> 
     <daughter>4</daughter> 
     <son>5</son> 
    </mother> 
<grandfather> 

ich /grandfather/mother alle Mütter mit dem XPath bekommen können, aber kann ich dann die Mutter Knoten, in einer separaten Funktion abfragen, den übergebenen Mutterknoten als die relative Wurzel der Verwendung nächste Abfrage?

Das Problem tritt auf, wenn das XML einen Namespace hat, den Sie registrieren müssen, damit der Xpath funktioniert. Mit SimpleXML wird das Namespacepräfix, das vor der ersten xpath-Abfrage registriert wurde, nicht im Abfrageergebnis beibehalten, daher müssen Sie es für nachfolgende Abfragen erneut registrieren.

Antwort

1

Das zweite Argument für DOMXpath::evaluate() ist der Kontext für den Ausdruck. Hier ist ein kleines Beispiel auf Ihrem xml arbeitet:

$document = new DOMDocument(); 
$document->loadXml($xml); 
$xpath = new DOMXpath($document); 

foreach ($xpath->evaluate('//mother') as $mother) { 
    var_dump(
    $xpath->evaluate('count(daughter)', $mother), 
    $xpath->evaluate('count(son)', $mother) 
); 
} 

Sie haben die Xpath-Instanz in eine Funktion, um die Namespace-Registrierung zu halten.

Es ist möglich, DOMDocument und die anderen DOMNode-Klassen zu erweitern, um die Registrierung auf Objektebene zu ermöglichen. Ich habe das in FluentDOM implementiert.

+0

Sie haben die Frage genau so beantwortet, wie ich es formuliert habe, also danke. Leider versuche ich verschiedene Klassenmethoden in meinem Code zu verwenden, um verschiedene Bits des XML zu verarbeiten. Dies bedeutet, dass ich sowohl das DOM-Dokument als auch den X-Pfad mit dem registrierten Namespace weitergeben muss, was ein wenig umständlich ist, insbesondere die Rückgabe. – Dom

+0

Nein, Sie müssen die Xpath-Instanz und die Kontextknoten passieren. Das Dokument ist in der Eigenschaft 'DOMNode :: $ ownerDocument' verfügbar. Wenn Sie das 'DOMDocument' erweitern, können Sie die Xpath-Instanz als eine Eigenschaft dafür speichern. – ThW

0

Sie können eine zweite Abfrage auf dem ursprünglichen XPathDocument tun, relativ zu Ihrem ersten Ergebnis-Knoten durch ./ in Beginn Ihres Query-String verwenden und den ersten Ergebnis-Knoten als zweiter Parameter verwendet:

$motherList=$xml->query('/grandfather/mother'); 
$aMother=$motherList[0]; 
$daughterList=$xml->query('./daugther',$aMother);