2016-11-07 10 views
2

У меня есть строка XML, фрагмент кода ниже:DOMXPath пути показывая вверх звездочками

<?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> 

Я преобразования XML в DOMDocument, чтобы сделать манипуляцию "проще":

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

I затем хотел бы использовать определенные значения, предпочтительно используя их пути:

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

Однако вышеуказанный запрос не возвращает никаких результатов.

В самом деле, когда я Переберите все элементы внутри документа:

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

Он возвращает что-то вроде этого:

/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] 

Как вы можете увидеть все элементы внутри <soap:Body> заменяются звездочками и индексами вместо имен элементов.

Выполнение запроса по этому пути работает, но мне будет нелегко поддерживать его, и я бы предпочел вместо этого использовать имена элементов.

+0

Вы внутренние элементы не содержат внешнюю NAMESPACE, так что вы не можете получить доступ к ним непосредственно из внешнего дерева. – Dekel

+0

@ Dekel спасибо за наконечник, повел меня в правильном направлении – andrewtweber

ответ

0

Другой вариант заключается в 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

Благодаря @Dekel для наконечника. Мне нужно было регистрировать как пространство имен, а затем указать пространство имен при запросе:

$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'); 

Теперь он работает.