php 使用具有多个命名空间的 SimpleXML 解析 XML

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/740730/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 23:42:39  来源:igfitidea点击:

parse an XML with SimpleXML which has multiple namespaces

phpsoapnamespacessimplexml

提问by perrohunter

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.

我有这个丑陋的 XML,它上面有很多命名空间,当我尝试用 simpleXML 加载它时,如果我指出第一个命名空间,我会得到一个 xml 对象,但是跟随带有其他命名空间的标签不会进入该对象。

How can I parse this XML ?

我怎样才能解析这个 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

但 $xml 对象将只包含以下内容

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

    [Body] => SimpleXMLElement Object
        (
        )

)

回答by Kieran Hall

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).

我认为您需要使用 XPath 注册命名空间和访问权限。像下面这样的东西应该让你开始(我没有能力测试这个)。

$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.

考虑一下,您可能不需要注册命名空间,因为它们已经存在于 XML 中。虽然不确定,但需要测试。

Hope this helps.

希望这可以帮助。

回答by IMSoP

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

1) 不要用print_r和朋友看什么是“在”一个 SimpleXML 对象。有关解释和替代方法,请参阅https://github.com/IMSoP/simplexml_debug

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

2) SimpleXML 中的命名空间支持由->children()->attributes()方法提供。

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

例如,您可以像这样获取 From 节点的 PartyId:

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

回答by troelskn

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-clientincluded as default.

那是一个肥皂信封。您可能希望使用soap-client 来抽象所有xml 解析。PHP附带了一个相当好的soap 客户端作为默认值。

回答by Thomas Byy

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

对于遇到此问题的其他任何人,我试图返回正确的数据时摸不着头脑,尽管最佳答案非常接近,但我还是花了一段时间才找到答案。最终使用这个页面来帮助:https: //www.w3schools.com/php/func_simplexml_registerxpathnamespace.asp

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

我相信 for 循环可以直接访问您需要的内容。IE

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

回答by Praveen D

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

有关更多详细信息,请阅读此处