在我的SOAP调用中,我需要有多个具有相同名称的元素。
我在这篇文章中找到了一种方法:http://andrecatita.com/code-snippets/php-soap-repeated-element-name/
Hoewever,由于某种原因,我得到的是BOGUS
代码,而不是所需的TranItem
。
php代码是:
$itemParams = new ArrayObject();
$items = new ArrayObject();
$tranItems = new stdClass();
$itemParams[0]->ItemId = '1234';
$itemParams[0]->Amount = '1';
$itemParams[0]->Price = '2000';
$itemParams[0]->TranRules = array('TranRule' => $itemRule);
$itemParams[1]->ItemId = '55555';
$itemParams[1]->Amount = '1';
$itemParams[1]->Price = '2000';
$itemParams[1]->TranRules = array('TranRule' => $itemRule);
$items->append($itemParams[0]);
$items->append($itemParams[1]);
$tranItems->TranItems = new SoapVar($items, SOAP_ENC_OBJECT, NULL, NULL, 'TranItems',$namespace);
...
...
$trans = array(
'TranItems' => $tranItems->TranItems
);
输出:
<ns1:TranItems>
<BOGUS>
<ItemId>1234</ItemId>
<Amount>1</Amount>
<Price>2000</Price>
<TranRules>
<item>
<key>TranRule</key>
<value/>
</item>
</TranRules>
</BOGUS>
<BOGUS>
<ItemId>55555</ItemId>
<Amount>1</Amount>
<Price>2000</Price>
<TranRules>
<item>
<key>TranRule</key>
<value/>
</item>
</TranRules>
</BOGUS>
</ns1:TranItems>
如何摆脱BOGUS元素并在其中包含TranItem?
答案 0 :(得分:1)
从此服务器:
$server = new SoapServer(null, array(
'uri' => 'http://test/',
));
$server->addFunction('test');
function test(){
$itemParams = new ArrayObject();
$items = array();
$itemParams[0]->ItemId = '1234';
$itemParams[0]->Amount = '1';
$itemParams[0]->Price = '2000';
$itemParams[0]->TranRules = array('TranRule' => 1);
$itemParams[1]->ItemId = '55555';
$itemParams[1]->Amount = '1';
$itemParams[1]->Price = '2000';
$itemParams[1]->TranRules = array('TranRule' => 2);
$items[] = new SoapVar($itemParams[0], SOAP_ENC_OBJECT);
$items[] = new SoapVar($itemParams[1], SOAP_ENC_OBJECT);
return new SoapVar($items, SOAP_ENC_OBJECT, NULL, NULL, 'TranItems');
}
$server->handle();
有了这个客户:
$client = new SoapClient(null, array(
'location' => 'http://localhost/server.php',
'uri' => 'http://test/',
'trace' => true
));
$p = $client->test();
$resp = $client->__getLastResponse();
$dom = new DOMDocument();
$dom->formatOutput = true;
$dom->preserveWhiteSpace = false;
$dom->loadXML($resp);
print '<pre>';
var_dump($p);
print htmlspecialchars($dom->saveXML());
我收到了这个回复:
object(stdClass)[2]
public 'TranItems' =>
array (size=2)
0 =>
object(stdClass)[3]
public 'ItemId' => string '1234' (length=4)
public 'Amount' => string '1' (length=1)
public 'Price' => string '2000' (length=4)
public 'TranRules' =>
array (size=1)
...
1 =>
object(stdClass)[4]
public 'ItemId' => string '55555' (length=5)
public 'Amount' => string '1' (length=1)
public 'Price' => string '2000' (length=4)
public 'TranRules' =>
array (size=1)
...
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:testResponse>
<ns1:TranItems xsi:type="SOAP-ENC:Struct">
<TranItems xsi:type="SOAP-ENC:Struct">
<ItemId xsi:type="xsd:string">1234</ItemId>
<Amount xsi:type="xsd:string">1</Amount>
<Price xsi:type="xsd:string">2000</Price>
<TranRules xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">TranRule</key>
<value xsi:type="xsd:int">1</value>
</item>
</TranRules>
</TranItems>
<TranItems xsi:type="SOAP-ENC:Struct">
<ItemId xsi:type="xsd:string">55555</ItemId>
<Amount xsi:type="xsd:string">1</Amount>
<Price xsi:type="xsd:string">2000</Price>
<TranRules xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">TranRule</key>
<value xsi:type="xsd:int">2</value>
</item>
</TranRules>
</TranItems>
</ns1:TranItems>
</ns1:testResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
稍加修改:
$items[] = new SoapVar($itemParams[0], SOAP_ENC_OBJECT, 'TransItem');
$items[] = new SoapVar($itemParams[1], SOAP_ENC_OBJECT, 'TransItem');
return new SoapVar($items, SOAP_ENC_ARRAY, 'TransItem', null);
你会得到:
array (size=2)
0 =>
object(stdClass)[2]
public 'ItemId' => string '1234' (length=4)
public 'Amount' => string '1' (length=1)
public 'Price' => string '2000' (length=4)
public 'TranRules' =>
array (size=1)
'TranRule' => int 1
1 =>
object(stdClass)[3]
public 'ItemId' => string '55555' (length=5)
public 'Amount' => string '1' (length=1)
public 'Price' => string '2000' (length=4)
public 'TranRules' =>
array (size=1)
'TranRule' => int 2
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="http://xml.apache.org/xml-soap" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:testResponse>
<return SOAP-ENC:arrayType="TransItem[2]" xsi:type="TransItem">
<item xsi:type="TransItem">
<ItemId xsi:type="xsd:string">1234</ItemId>
<Amount xsi:type="xsd:string">1</Amount>
<Price xsi:type="xsd:string">2000</Price>
<TranRules xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">TranRule</key>
<value xsi:type="xsd:int">1</value>
</item>
</TranRules>
</item>
<item xsi:type="TransItem">
<ItemId xsi:type="xsd:string">55555</ItemId>
<Amount xsi:type="xsd:string">1</Amount>
<Price xsi:type="xsd:string">2000</Price>
<TranRules xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">TranRule</key>
<value xsi:type="xsd:int">2</value>
</item>
</TranRules>
</item>
</return>
</ns1:testResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
说明:
肥皂是作为跨语言传输协议开发的。在大多数语言中,没有关联数组这样的东西。这就是为什么你必须将$itemParams[0]
编码为对象的原因。 soap的大多数目标语言(如Java)具有强类型,因此当您不为soap编码器提供类型时,它将生成一个。数组也是如此。在强类型语言中,每个数组只能包含一种对象。总结一下:你将php关联数组编码为TYPE的对象,其中TYPE将成为节点名称,然后如果返回多个元素:将它们编码为包含特定TYPE对象的soap数组。未编码的数组(因为它可以包含多种不同类型)被转换为具有多个项目节点的映射,每个节点都具有关键节点和值节点。
改变这个:
$items[] = new SoapVar($itemParams[0], SOAP_ENC_OBJECT, null, null, 'TranItems');
到那个:
$items[] = new SoapVar($itemParams[0], SOAP_ENC_OBJECT);
你会得到BOGUS。
答案 1 :(得分:1)
我最终得到了这个有效的代码 - 可能不是最好的解决方案,但这是唯一对我有用的代码:
class Item {
public $ItemId;
public $Amount;
public $Price;
public $TranRules;
}
class TranRule {
public $RuleId;
public $Value;
}
$rule1 = new TranRule();
$rule1->RuleId = '2';
$rule1->Value = '300';
$rule1 = new SoapVar($rule1, SOAP_ENC_OBJECT, NULL, NULL, 'TranRule', 'http://gate.ibod.cz/v1/api.svc');
$return_array = new ArrayObject();
$new_item = new Item();
$new_item->ItemId = '13245';
$new_item->Amount = "1";
$new_item->Price = "500";
$new_item->TranRules = $rule1;
$new_item = new SoapVar($new_item, SOAP_ENC_OBJECT, null, null, 'TranItem');
$return_array->append($new_item);
$new_item = new Item();
$new_item->ItemId = '456789';
$new_item->Amount = "1";
$new_item->Price = "20000";
$new_item->TranRules = $rule2;
$new_item = new SoapVar($new_item, SOAP_ENC_OBJECT, null, null, 'TranItem');
$return_array->append($new_item);
$tranItems = new stdClass();
$tranItems->TranItems = new SoapVar($return_array, SOAP_ENC_OBJECT, NULL, NULL, 'TranItems');