2016-11-07 6 views
2

ich eine XML-Zeichenfolge haben, Schnipsel unten:DOMXPath Pfade als Sternchen zeigt sich

<?xml version="1.0"?> 
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
     xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soap:Body> 
     <SendPurchases xmlns="urn:services.insurance"> 
      <Partner> 
       <UserID>MyCompany</UserID> 
       <Password>ABC123</Password> 
      </Partner> 
      <PurchasesRequest> 
       <Total>100</Total> 
      </PurchasesRequest> 
     </SendPurchases> 
    </soap:Body> 
</soap:Envelope> 

ich die XML-Daten in einer DOMDocument bin Umwandlung Manipulation zu machen "leichter":

$doc = new DOMDocument(); 
$doc->loadXML($xml); 
$xpath = new DOMXPath($doc); 

I möchte dann bestimmte Werte manipulieren, vorzugsweise unter Verwendung ihrer Pfade:

$elements = $xpath->query('/soap:Envelope/soap:Body/SendPurchases/Partner/UserID'); 

Die obige Abfrage gibt jedoch keine Ergebnisse zurück.

In der Tat, wenn ich Schleife durch alle Elemente innerhalb des Dokuments:

foreach ($doc->getElementsByTagName('*') as $node) { 
    echo $node->getNodePath() . "\n"; 
} 

es so etwas wie diese gibt:

/soap:Envelope/soap:Body 
/soap:Envelope/soap:Body/* 
/soap:Envelope/soap:Body/*/*[1] 
/soap:Envelope/soap:Body/*/*[1]/*[1] 
/soap:Envelope/soap:Body/*/*[1]/*[2] 
/soap:Envelope/soap:Body/*/*[2] 
/soap:Envelope/soap:Body/*/*[2]/*[1] 

Wie Sie alle Elemente innerhalb von sehen <soap:Body> werden anstelle der Elementnamen durch Sternchen und Indizes ersetzt.

Abfragen entlang dieses Pfades funktioniert, aber wird nicht leicht für mich zu pflegen, und ich würde sehr viel lieber die Elementnamen stattdessen verwenden.

+0

Sie innere Elemente enthalten nicht die äußeren Namespace, so dass Sie sie nicht direkt von dem äußeren Baum zugreifen. – Dekel

+0

@Dekel danke für den Tipp, führte mich in die richtige Richtung – andrewtweber

Antwort

0

Eine weitere Möglichkeit ist use local-name():

$xml = '<?xml version="1.0"?> 
    <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
      xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 
     <soap:Body> 
      <SendPurchases xmlns="urn:services.insurance"> 
       <Partner> 
        <UserID>MyCompany</UserID> 
        <Password>ABC123</Password> 
       </Partner> 
       <PurchasesRequest> 
        <Total>100</Total> 
       </PurchasesRequest> 
      </SendPurchases> 
     </soap:Body> 
    </soap:Envelope>'; 
$doc = new DOMDocument(); 
$doc->loadXML($xml); 
$xpath = new DOMXPath($doc); 

$elements = $xpath->query("//*[local-name()='UserID']"); 

var_dump($elements->item(0)->nodeValue); 
// string(9) "MyCompany" 
2

Dank @Dekel für den Tipp. Ich brauchte beiden Namensräume registrieren und dann den Namespace angeben, bei der Abfrage:

$xpath = new DOMXPath($doc); 
$xpath->registerNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/'); 
$xpath->registerNamespace('insr', 'urn:services.insurance'); 

$elements = $xpath->query('/soap:Envelope/soap:Body/insr:SendPurchases/insr:Partner/insr:UserID'); 

Jetzt es funktioniert.