2009-04-11 8 views
10

J'ai ce XML moche qui a beaucoup d'espaces de noms dessus, quand j'essaie de le charger avec simpleXML si j'indique le premier espace de noms j'obtiendrais un objet xml, mais les balises suivantes avec d'autres espaces de noms ne le ferait pas à l'objet.analyser un XML avec SimpleXML qui a plusieurs espaces de noms

Comment puis-je analyser ce 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 essayant d'analyser avec le code suivant

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

mais l'objet $ xml ne contiendrait les éléments suivants

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

    [Body] => SimpleXMLElement Object 
     (
     ) 

) 

Répondre

28

Je pense que vous devez enregistrer le espace de nommage et l'accès avec XPath. Quelque chose comme ce qui suit devrait vous permettre d'aller (je n'ai pas la possibilité de tester cela).

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

Ensuite, vous pouvez faire quelque chose comme:

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

Vous ne pouvez pas besoin d'enregistrer l'espace de nommage, d'y penser, car ils sont alredy dans le document XML. Pas sûr à ce sujet, aurait besoin de tester.

Espérons que cela aide.

+1

simplement vous BRILLIAN non seulement aidé à résoudre mon problème, mais aussi indiqué clairement comment XPath a travaillé :) merci! – perrohunter

+0

Il n'est pas nécessaire de basculer vers XPath simplement parce que vous utilisez des espaces de noms. – IMSoP

+0

Si vous utilisez XPath, vous devez enregistrer explicitement les espaces de noms comme dans le code ci-dessus, sinon un échec se produit. – Bobulous

7

1) N'utilisez pas print_r et vos amis pour voir ce qui est "dans" un objet SimpleXML. Voir https://github.com/IMSoP/simplexml_debug pour l'explication et les alternatives.

2) La prise en charge des espaces de noms dans SimpleXML est fournie par les méthodes ->children() et ->attributes().

Par exemple, vous pouvez obtenir le PartyId du nœud d'comme ceci:

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

C'était le commentaire le plus utile pour moi, bon que vous indiquiez que print_r etc ne fonctionne pas et fournisse un lien vers simplexml_debug, les accessoires! –

+0

Ces fonctions de débogage sont vraiment utiles pour les nouveaux utilisateurs. – xdbas

-1

Essayez cette

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

    var_dump($soap_client->__getFunctions()); 

Pour plus de détails read here

0

Pour quelqu'un d'autre qui vient à travers ce que je J'ai gratté la tête en essayant de retourner les bonnes données et même si la réponse était extrêmement proche, il m'a fallu du temps pour trouver la réponse. Finalement utilisé cette page pour aider: https://www.w3schools.com/php/func_simplexml_registerxpathnamespace.asp

Je crois que la boucle for peut accéder directement à ce dont vous avez besoin. à savoir

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