2009-04-11 14 views
10

Tengo este feo XML que tiene muchos espacios de nombres, cuando intento cargarlo con simpleXML si indico el primer espacio de nombres obtendría un objeto xml, pero las siguientes etiquetas con otros espacios de nombres no llegaría al objeto.analizar un XML con SimpleXML que tiene varios espacios de nombres

¿Cómo puedo analizar este 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 tratando de analizarlo con el siguiente código

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

pero el objeto $ xml que sólo contienen la siguiente

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

    [Body] => SimpleXMLElement Object 
     (
     ) 

) 

Respuesta

28

creo que es necesario para registrar el namespacing y acceso con XPath. Algo como lo siguiente debería ayudarlo (no tengo la posibilidad de probar esto).

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

A continuación, puede hacer algo como:

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

Puede que no necesite para registrar el namespacing, pensando en ello, ya que son todavia presente en el XML. Sin embargo, no estoy seguro de esto, necesitaría probarlo.

Espero que esto ayude.

+1

Simplemente Brillian que no sólo ayudó a resolver mi problema, pero también aclaró cómo XPath trabajó :) gracias! – perrohunter

+0

No es necesario cambiar a XPath solo porque está usando espacios de nombres. – IMSoP

+0

Si está utilizando XPath, entonces necesita registrar los espacios de nombres explícitamente como en su código anterior, de lo contrario se produce una falla. – Bobulous

7

1) No use print_r y sus amigos para ver qué es "en" un objeto SimpleXML. Vea https://github.com/IMSoP/simplexml_debug para una explicación y alternativas.

2) El soporte del espacio de nombres en SimpleXML es proporcionado por los métodos ->children() y ->attributes().

Por ejemplo, usted podría tener la PartyId del Desde el nodo de esta manera:

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

. Este fue el comentario más útil para mí, es bueno señalar que print_r, etc. no funciona y proporciona un enlace a simplexml_debug, props! –

+0

Esas funciones de depuración son realmente útiles para las personas que son nuevas en esto. – xdbas

-1

probar este

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

    var_dump($soap_client->__getFunctions()); 

Para más detalles read here

0

Para cualquier otra persona que se encuentra con esto Me rasqué la cabeza tratando de devolver los datos correctos y, aunque la respuesta principal fue extremadamente cerrada, aún tardé un rato en encontrar la respuesta. Finalmente usé esta página para ayudar: https://www.w3schools.com/php/func_simplexml_registerxpathnamespace.asp

Creo que el bucle for puede acceder directamente a lo que necesita. es decir,

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