2009-04-11 12 views
10

Ho questo brutto XML che ha un sacco di spazi dei nomi su di esso, quando provo a caricarlo con simpleXML se indico il primo spazio dei nomi otterrei un oggetto xml, ma i seguenti tag con altri spazi dei nomi non potrebbe arrivare all'oggetto.analizza un XML con SimpleXML che ha più spazi dei nomi

Come analizzare questo XML?

<?xml version="1.0" encoding="UTF-8"?> 
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soap-env:Header> 
     <eb:MessageHeader xmlns:eb="http://www.ebxml.org/namespaces/messageHeader" eb:version="1.0" soap-env:mustUnderstand="1"> 
      <eb:From> 
       <eb:PartyId eb:type="URI">wscompany.com</eb:PartyId> 
      </eb:From> 
      <eb:To> 
       <eb:PartyId eb:type="URI">mysite.com</eb:PartyId> 
      </eb:To> 
      <eb:CPAId>something</eb:CPAId> 
      <eb:ConversationId>moredata.com</eb:ConversationId> 
      <eb:Service eb:type="compXML">theservice</eb:Service> 
      <eb:Action>theaction</eb:Action> 
      <eb:MessageData> 
       <eb:MessageId>a certain messageid</eb:MessageId> 
       <eb:Timestamp>2009-04-11T18:43:58</eb:Timestamp> 
       <eb:RefToMessageId>mid:areference</eb:RefToMessageId> 
      </eb:MessageData> 
     </eb:MessageHeader> 
     <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext"> 
      <wsse:BinarySecurityToken valueType="String" EncodingType="wsse:Base64Binary">an impresive binary security toekn</wsse:BinarySecurityToken> 
     </wsse:Security> 
    </soap-env:Header> 
    <soap-env:Body> 
     <SessionCreateRS xmlns="http://www.opentravel.org/OTA/2002/11" version="1" status="Approved"> 
      <ConversationId>the goodbye token</ConversationId> 
     </SessionCreateRS> 
    </soap-env:Body> 
</soap-env:Envelope> 

im cercando di analizzarlo con il seguente codice

<?php 
$xml = simplexml_load_string($res,NULL,NULL,"http://schemas.xmlsoap.org/soap/envelope/"); 
?> 

ma l'oggetto $ xml sarebbe solo contenere le seguenti

SimpleXMLElement Object 
(
    [Header] => SimpleXMLElement Object 
     (
     ) 

    [Body] => SimpleXMLElement Object 
     (
     ) 

) 

risposta

28

Penso che è necessario registrare il namespacing e l'accesso con XPath. Qualcosa come il seguente dovrebbe farti andare (non ho la possibilità di testare questo).

$xml = simplexml_load_string($res, NULL, NULL, "http://schemas.xmlsoap.org/soap/envelope/"); 
$xml->registerXPathNamespace('soap-env', 'http://schemas.xmlsoap.org/soap/envelope/'); 
$xml->registerXPathNamespace('eb', 'http://www.ebxml.org/namespaces/messageHeader'); 
$xml->registerXPathNamespace('wsse', 'http://schemas.xmlsoap.org/ws/2002/12/secext'); 

Poi si può fare qualcosa di simile:

foreach($xml->xpath('//eb:MessageHeader') as $header) 
{ 
    var_export($header->xpath('//eb:CPAId')); // Should output 'something'. 
} 

Potrebbe non essere necessario registrare il namespacing, a pensarci, in quanto sono presenti nel alredy XML. Non sono sicuro su questo, avrebbe bisogno di testare.

Spero che questo aiuti.

+1

Semplicemente brillian non solo mi ha aiutato a risolvere il mio problema, ma anche chiarito come XPath lavorato :) grazie! – perrohunter

+0

Non è necessario passare a XPath solo perché si utilizzano gli spazi dei nomi. – IMSoP

+0

Se si utilizza XPath, è necessario registrare gli spazi dei nomi in modo esplicito come nel codice precedente, altrimenti si verifica un errore. – Bobulous

7

1) Non utilizzare print_r e gli amici per vedere cosa è "dentro" un oggetto SimpleXML. Vedere https://github.com/IMSoP/simplexml_debug per spiegazioni e alternative.

2) Il supporto dello spazio dei nomi in SimpleXML è fornito dai metodi ->children() e ->attributes().

Per esempio si potrebbe ottenere il PartyId del Da nodo di come questo:

$from_party = (string)$xml->children('soap-env', true)->Header->children('eb', true)->MessageHeader->From->PartyId; 
+0

Questo è stato il commento più utile per me, bene che fai notare che print_r etc non funziona e fornisci un link a simplexml_debug, oggetti di scena! –

+0

Queste funzioni di debug sono davvero utili per le persone nuove a questo. – xdbas

-1

Prova questa

$soap_url = 'http://path/wsdl/somefile.wsdl'; 
    $soap_client = new SoapClient($soap_url); 

    var_dump($soap_client->__getFunctions()); 

Per ulteriori dettagli read here

0

Per chiunque altro che si imbatte in questo ho mi grattai la testa cercando di restituire i dati corretti e sebbene la risposta più alta fosse estremamente vicina, mi ci volle ancora un po 'per trovare la risposta. Alla fine ha utilizzato questa pagina per aiutare: https://www.w3schools.com/php/func_simplexml_registerxpathnamespace.asp

Credo che il ciclo for possa accedere direttamente a ciò che è necessario. vale a dire

foreach($xml->xpath('//eb:CPAId') as $header) 
{ 
    echo $header; // Should output 'something'. 
} 
Problemi correlati