php – 如何填充复合消息并作为SoapServer响应XML返回?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了php – 如何填充复合消息并作为SoapServer响应XML返回?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含8906字,纯文字阅读大概需要13分钟。
内容图文
![php – 如何填充复合消息并作为SoapServer响应XML返回?](/upload/InfoBanner/zyjiaocheng/743/20dbb4e3cbdb46829e51d7a034dcfae6.jpg)
我正在设置一个SOAP Web服务,它应该返回一个复合消息.
此消息的有效实例如下:
<dl190Response xmlns="http://pse/">
<cdhead cisprik="5563167"/>
<mvts>
<mvts_S att="a1">
<x>x1</x>
<w>w1</w>
</mvts_S>
<mvts_S>
<x>x2</x>
<w>w2</w>
</mvts_S>
</mvts>
</dl190Response>
所有这些都在wsdl中得到了很好的定义:
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://pse/"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
name="PSE"
targetNamespace="http://pse/">
<types>
<xs:schema xmlns="http://pse/" targetNamespace="http://pse/">
<xs:complexType name="cdhead_T">
<xs:attribute name="cisprik" type="xs:long"/>
</xs:complexType>
<xs:complexType name="mvts_T">
<xs:sequence>
<xs:element name="mvts_S" type="mvts_S_T" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="mvts_S_T">
<xs:sequence>
<xs:element name="x" type="xs:string"/>
<xs:element name="w" type="xs:string"/>
</xs:sequence>
<xs:attribute name="att" type="xs:string" use="optional"/>
</xs:complexType>
</xs:schema>
</types>
<message name="DL190Req">
<part name="cdhead" type="tns:cdhead_T"/>
</message>
<message name="DL190Res">
<part name="cdhead" type="tns:cdhead_T"/>
<part name="mvts" type="tns:mvts_T"/>
</message>
<portType name="DLPortType">
<operation name="dl190">
<input message="tns:DL190Req"/>
<output message="tns:DL190Res"/>
</operation>
</portType>
<binding name="DLBinding" type="tns:DLPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="dl190">
<soap:operation soapAction="http://www.testServer.com/test_soap.php#dl190"/>
<input>
<soap:body use="literal" namespace="http://pse/"/>
</input>
<output>
<soap:body use="literal" namespace="http://pse/"/>
</output>
</operation>
</binding>
<service name="PSE">
<port name="DLPortType" binding="tns:DLBinding">
<soap:address location="http://www.testServer.com/test_soap.php"/>
</port>
</service>
</definitions>
我一直在服务器端test_soap.php无休止地工作,但是我没有成功.
在返回XML之前正常工作的部分原因如下:
<?php
class PSE {
function dl190 ($arg) {
//I don't need to extract the input data just now
mysql_connect('127.0.0.1:3306', 'user', 'password');
mysql_select_db('myDatabase');
$xml = new SimpleXMLElement('<dl190Res/>');
$xml -> addChild('cdhead');
$mvts = $xml -> addChild('mvts');
$rows = mysql_query('select * from trx');
while($data = mysql_fetch_assoc($rows)) {
$mvts_S = $mvts -> addChild('mvts_S');
foreach($data as $key => $value) {
if ($key == 'att') { $mvts_S -> addAttribute($key, $value);}
else {$mvts_S -> addChild($key, $value);}
}
};
$dom = dom_import_simplexml ($xml) -> ownerDocument;
// now respond to the request and return the XML
}
};
ini_set( "soap.wsdl_cache_enabled", "0");
$server = new SoapServer ("test.wsdl");
$server -> setClass ('PSE');
$server -> setObject (new PSE());
$server -> handle();
?>
我尝试了几乎所有我能想到的答案,但我没有成功.我能够为之前只包含一部分的消息做同样的事情(请参阅我最近的问题答案).
但在这里,有两个消息部分,我没有成功.
$xml内容的调试显示,当肥皂服务器将其包装到Envelope Body中时,它正是我希望看到的.
实际上情况与只有一个消息部分的情况不同:只要我首先剥离XML声明,我就可以从一个部分创建一个新的SoapVar,并返回它.在这里我不能这样做,因为返回值由两部分组成.
所以我想知道我现在应该做以下哪些事情:
>为响应消息声明一个类,然后填充并返回该消息
>使用SoapVar和/或SoapParam执行一些魔法(请注意,我已经尝试了很多)
>使用数组和SoapVar执行一些魔法(已经尝试过很多)
>不知何故(如何?)向wsdl寻求帮助
>完全不同的东西
>使用SoapServer退出整个噩梦,从头开始创建自己的http响应
我很感谢所有这方面的帮助,所以你们所有的肥皂专家都会毫不犹豫地试着回答这个问题!
加成
作为临时解决方法,我编辑了WSDL,将响应消息更改为仅包含一个部分.这允许我将期望的消息作为预期的两个部分(或任何其他消息)的串联传递,因为SoapVar没有对返回的值执行消息定义的结构WSDL检查):
$xml1 = new SimpleXMLElement('<cdhead/>');
$xml1 -> addAttribute ('xmlns', 'http://pse/');
$xml1 -> addAttribute ('cisprik', $newCisprik);
$xml2 = new SimpleXMLElement('<mvts/>');
$rows = mysql_query('select * from trx');
while($data = mysql_fetch_assoc($rows)) {
$mvts_S = $xml2 -> addChild('mvts_S');
foreach($data as $key => $value) {
if ($key == 'att') { $mvts_S -> addAttribute($key, $value);}
else {$mvts_S -> addChild($key, $value);}
}
};
$dom1 = dom_import_simplexml ($xml1) -> ownerDocument;
$dom2 = dom_import_simplexml ($xml2) -> ownerDocument;
$part1 = $dom1 -> saveXML($dom1 -> documentElement);
$part2 = $dom2 -> saveXML($dom2 -> documentElement);
$result = new SoapVar ($part1 . $part2, XSD_ANYXML);
特别之处在于,串联当然不是有效的XML,缺少周围的根元素,但SoapVar无论如何都能够解析它.
所以它是:任何在SoapVar和SoapParam / SoapServer中具有详细洞察力的人都可以解释是否可以返回两个消息部分?
并解释如何这样做?
或者,或者,在其他SOAP设置中提供有关如何执行此操作的详细信息?
解决方法:
我尝试并设置了你的最小SoapServer,这就是我所做的:
>将wsdl和PHP脚本复制到一个文件夹.
>更改wsdl位置引用以指向php脚本.
>将WSDL导入SoapUI – 强烈推荐它,它是免费的!
>试图打电话给服务.
这是我的呼叫请求:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:pse="http://pse/">
<soapenv:Header/>
<soapenv:Body>
<pse:dl190>
<cdhead cisprik="0"/>
</pse:dl190>
</soapenv:Body>
</soapenv:Envelope>
它最初没有用,因为你调用了数据库,但我知道你真的只需要一个如何在soap层上正确响应的解决方案,你会弄清楚其余部分.
这是一个简单的解决方案:
<?php
class PSE
{
public function dl190($arg)
{
//var_dump($arg) is:
//object(stdClass)#3 (1) {
// ["cisprik"]=> int(0)
//}
$fakeResult = array();
$fakeResult[0] = new stdClass();
$fakeResult[0]->cisprik = 23;
$fakeResult[1] = array();
$fakeResult[1][0] = new stdClass();
$fakeResult[1][0]->att = "a1";
$fakeResult[1][0]->x = "x1";
$fakeResult[1][0]->w = "w1";
$fakeResult[1][1] = new stdClass();
//$fakeResult[1][1]->att = "a1";
$fakeResult[1][1]->x = "x2";
$fakeResult[1][1]->w = "w2";
return $fakeResult;
}
}
//ini_set("soap.wsdl_cache_enabled", "0");
$server = new SoapServer ("wsdl.xml");
$server->setObject(new PSE());
$server->handle();
请注意,PHP基本上只在请求参数中发出stdClass和数组的混合(我在顶部转储了你得到的注释).这是一件令人伤心的事情,但我认为在同一级别做出回应是不公平的事情,而不是通过回归使用XML来使事情变得更糟.
如果针对此代码执行上述请求,您将获得此soap响应:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://pse/">
<SOAP-ENV:Body>
<ns1:dl190Response>
<cdhead cisprik="23"/>
<mvts>
<mvts_S att="a1">
<x>x1</x>
<w>w1</w>
</mvts_S>
<mvts_S>
<x>x2</x>
<w>w2</w>
</mvts_S>
</mvts>
</ns1:dl190Response>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
但仍有改进的余地. PHP SoapServer(以及SoapClient)也有一个名为classmap的功能,我强烈建议您使用它.如果您的IDE支持任何类型的PHPDoc自动完成,您几乎可以在任何处理正确设置值的地方利用它.
这是我的版本,带有类图定义.请注意,我使用“PSE”将它们全部加上前缀,以突出显示类名不需要在WSDL中的complexTypes之后命名的事实.
<?php
class PSE
{
public function dl190(PSE_cdhead_T $arg)
{
// var_dump($arg) is:
// object(PSE_cdhead_T)#3 (1) {
// ["cisprik"]=> int(0)
// }
$fakeResult = array();
$fakeResult[0] = new PSE_cdhead_T();
$fakeResult[0]->cisprik = 23;
$fakeResult[1] = array();
$fakeResult[1][0] = new PSE_mvts_S_T();
$fakeResult[1][0]->att = "a1";
$fakeResult[1][0]->x = "x1";
$fakeResult[1][0]->w = "w1";
$fakeResult[1][1] = new PSE_mvts_S_T();
//$fakeResult[1][1]->att = "a1";
$fakeResult[1][1]->x = "x2";
$fakeResult[1][1]->w = "w2";
return $fakeResult;
}
}
class PSE_cdhead_T {
/**
* @var int
*/
public $cisprik;
}
class PSE_mvts_S_T {
/**
* @var string
*/
public $att;
/**
* @var string
*/
public $x;
/**
* @var string
*/
public $w;
}
//ini_set("soap.wsdl_cache_enabled", "0");
$classmap = array(
'cdhead_T' => 'PSE_cdhead_T',
'mvts_S_T' => 'PSE_mvts_S_T',
);
$serverOptions = array(
'encoding' => 'utf-8',
'classmap' => $classmap,
'features' => SOAP_SINGLE_ELEMENT_ARRAYS,
);
$server = new SoapServer ("wsdl.xml", $serverOptions);
$server->setObject(new PSE());
$server->handle();
不幸的是,一个烦人的问题没有得到解决:在你的响应中,你不能使用一个类,但必须使用一个数组,而没有任何提示将哪个索引参数映射到哪个xml结果.这真的很糟糕,但要改变它,你将不得不改变WSDL.
我很不高兴地报告,我在创建WSDL文件没有专家.我尝试添加复杂类型作为响应中的唯一元素.如果你看看我的第二个版本中的转储,你会看到你得到一个类PSE_cdhead_T,它是请求消息唯一部分的映射complexType.
因为响应消息有两个部分,所以SoapServer必须将它们放在一个数组中.没有可能的命名引用.我建议你在这里添加一个新的complexType,并在地图中相应地创建一个新类,如下所示:
class PSE_DL190_Response
{
/**
* @var PSE_cdhead_T
*/
public $cdhead;
/**
* @var PSE_mvts_S_T[]
*/
public $mvts;
}
然后,您可以更轻松地准备响应:
$fakeResult = new PSE_DL190_Response();
$fakeResult->cdhead = new PSE_cdhead_T(); // Set the one cdhead structure
$fakeResult->mvts[] = new PSE_mvts_S_T(); // Add one mvts structure;
这很可能会导致您对XML响应的更改 – 但我无法评估其影响.
最后一个想法:有一些用于PHP的WSDL代码生成器,您可以尝试.他们将自动生成类图所需的类.上次我尝试它们时,它们似乎工作,但不是我测试的所有WSDL文件. Soap定义似乎过于复杂,无法做到这一点.但如果它有效,那么它是值得的,而不是手动创建它们.
内容总结
以上是互联网集市为您收集整理的php – 如何填充复合消息并作为SoapServer响应XML返回?全部内容,希望文章能够帮你解决php – 如何填充复合消息并作为SoapServer响应XML返回?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。