使用PHP的SOAP修改服务器端发送的XML

时间:2012-09-29 18:15:14

标签: php soap soapserver

关于PHP的SoapClient和SoapServer,WSDL模式的问题。

我需要,让我们说,用其中的数据创建XML的某个部分的摘要。使用SoapClient很容易。我从类__doRequest()重载SoapClient方法,对某些元素进行哈希处理,并将其作为元素<Hash></Hash>添加到<SOAP-ENV:Header/>中。 然后我将生成的XML发送到调用parent::__doRequest()的SOAPServer。

我需要对响应XML做同样的事情。在服务器方面,我遇到了困难。似乎服务器只能将数据作为嵌套数组或对象发送,并以某种方式插入到客户端的响应XML中。我尝试使用SoapServer的响应发送XML,然后返回空XML。

我真的需要解析和修改服务器端的XML(制作哈希,数字签名等),但到目前为止,无论我在哪里搜索,我都无法找到答案。我真的非常感谢你的帮助。感谢。

1 个答案:

答案 0 :(得分:0)

您必须获取XML字符串不带XML声明并使用SoapVar解析它。
有关详细信息,请参阅how-return-custom-xml-response-in-soapserver-response

简而言之,就是这个 您可以根据输入构建DOMDocument以及需要将其添加到其中的任何其他内容。 XSLT是解析和更改XML的好方法(有关如何在php中使用xslt的简单示例,请再次参见上面的链接)。
然后,从您要返回的DOMNode中选择DOMDocument,并将saveXML与此节点一起用作参数。这会将所需的XML保存为字符串而不使用声明。没有参数的普通saveXML()会将根节点保存为字符串,包括声明。 因此:

$nodes = $dom -> getElementsByTagName ('chooseTheElementYouWishToReturn');
$node = $nodes -> item(0);

$result = new SoapVar ($dom -> saveXML($node), XSD_ANYXML);
return ($result);

当你想要返回根元素时,这当然也有效:

$result = new SoapVar ($dom -> saveXML($dom -> documentElement), XSD_ANYXML);
return ($result);

<强> ADDITION

我注意到你希望在SOAP标题中添加一些东西,而不是添加到正文中 这有点棘手,但可以实现 - 我希望下面的内容符合您的需求。

首先,添加标题详细信息只能在函数脚本中完成,然后函数必须将服务器变量声明为全局,以便引用声明的全局(函数外部),如下所示:

<?php   
    class mySOAPclass {
        function xxx ($arg) {
            global $server;

            // your code for the header part
            // example
            $auth = array();
            $auth['UserName'] = 'user';
            $auth['Password'] = 'pw';
            $header = new SoapVar ($auth, SOAP_ENC_OBJECT);
            // end example

            $header = new SoapHeader ('http://schemas.xmlsoap.org/soap/header/', 'credentials', $header, false);
            $server -> addSoapHeader ($header);

            // your code for the body part, assuming it results in a DOM $dom

            $result = new SoapVar ($dom -> saveXML($dom -> documentElement), XSD_ANYXML);

            return ($result);
        }

    ini_set( "soap.wsdl_cache_enabled", "0");
    $server = new SoapServer ("yourOwn.wsdl");
    $server -> setClass ('mySOAPclass');
    $server -> setObject (new mySOAPclass());
    $server -> handle();
?>

请注意,首先需要从数组中构造SoapVar;如果直接将数组提供给标题,则会得到丑陋的item / key和item / value节点。

以上导致以下返回结构:

<SOAP-ENV:Envelope 
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:ns1="http://schemas.xmlsoap.org/soap/header/">
    <SOAP-ENV:Header>
        <ns1:credentials>
            <UserName>user</UserName>
            <Password>pw</Password>
        </ns1:credentials>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body>
        ...
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>