parse an XML with SimpleXML which has multiple nam

2019-01-02 18:58发布

问题:

I have this ugly XML which has alot of namespaces on it, when I try to load it with simpleXML if i indicate the first namespace I'd get an xml object ,but following tags with other namespaces would not make it to the object.

How can I parse this 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 trying to parse it with the following code

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

but the $xml object would only contain the following

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

    [Body] => SimpleXMLElement Object
        (
        )

)

回答1:

I think you need to register the namespacing and access with XPath. Something like the following should get you going (I haven't the facility to test this).

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

Then you can do something like:

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

You may not need to register the namespacing, thinking about it, as they are alredy present in the XML. Not sure on this though, would need to test.

Hope this helps.



回答2:

1) Do not use print_r and friends to see what is "in" a SimpleXML object. See https://github.com/IMSoP/simplexml_debug for explanation and alternatives.

2) Namespace support in SimpleXML is provided by the ->children() and ->attributes() methods.

For example you could get the PartyId of the From node like this:

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


回答3:

That's a soap-envelope. You might want to use a soap-client to abstract all the xml-parsing away. PHP comes with a rather good soap-client included as default.



回答4:

For anyone else that comes across this I scratched my head trying to return the correct data and although the top answer was extremely close it still took me a while to find the answer. Eventually used this page to help: https://www.w3schools.com/php/func_simplexml_registerxpathnamespace.asp

I believe the for loop can directly access what you need. i.e.

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


回答5:

Try this

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

   var_dump($soap_client->__getFunctions());

For more detail read here



标签: