好的,所以我让SOAPClient进行调用。如果我使用__getLastResponse(),我会在XML中得到一行,如下所示:
<Discount xsi:type="ProgressivePromotion" from="2013-05-05T00:00:00" to="2013-05-14T00:00:00" type="Percent" value="20" name="Special Deal"/>
但是,我的SOAPClient类中的函数返回了一个对象。
PHP类中调用的代码是:
function SearchHotels($parameters ){
$funcRet = null;
try {
$funcRet = $this->client->SearchHotels($parameters);
} catch ( Exception $e ) {
echo "(SearchHotels) SOAP Error:n-------------------------------------n" . $e->getMessage () . "nn";
echo "(SearchHotels) Request:n-------------------------------------n" . $this->client->__getLastRequest() . "nn";
echo "(SearchHotels) Response:n-------------------------------------n" . $this->client->__getLastResponse() . "nn";
}
return $funcRet;
}
当我使用返回的对象时,我可以从Discount元素访问以下属性:
类型:ProgressivePromotion
起始时间:2013-05-05T00:00:00
至:2013-05-14T00:00:00
值:20
名称:特价
但我无法访问type="Percent"
SOAPClient似乎忽略了xsi:type中的xsi命名空间,只将该属性存储为type。
那么,我如何访问xsi:type AND type,这样我就可以判断我的折扣是百分比还是金额,或者其他类型的折扣?
顺便说一句,在我的SOAP响应的顶部,我没有看到任何东西声明xsi是什么。
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SearchHotelsResponse xmlns="http://tourico.com/webservices/hotelv3">
<SearchHotelsResult>
<Info xmlns="http://schemas.tourico.com/webservices/hotelv3" version="9.71" culture="en-US" serverTime="2013-02-06T14:49:58.3500117-05:00"/>
<HotelList xmlns="http://schemas.tourico.com/webservices/hotelv3">
编辑
如果我var_dump返回的对象,我会得到
stdClass Object
(
[SearchHotelsResult] => stdClass Object
(
[Info] => stdClass Object
(
[version] => 9.71
[culture] => en-US
[serverTime] => 2013-02-06T15:17:59.8445748-05:00
)
[HotelList] => stdClass Object
(
[Hotel] => Array
(
[0] => stdClass Object
[RoomTypes] => stdClass Object
(
[RoomType] => Array
(
[0] => stdClass Object
(
[Discount] => stdClass Object
(
[from] => 2013-05-05T00:00:00
[to] => 2013-05-14T00:00:00
[type] => ProgressivePromotion
[value] => 20
[name] => Special Deal
)
看看我是如何丢失type="Amount"的?
我不能通过调用折扣
echo $result->SearchHotelsResult->HotelList->Hotel[0]->RoomTypes->RoomType[0]->Discounts->type;
因为我有
Undefined property: stdClass::$Discounts Notice: Trying to get property of non-object
因此,我将整个对象转换为一个巨大的多维数组,并以这种方式访问事物。无论如何,type="Amount"都不会被提取。
我用这种方法解决了这个问题。
<?php
class fixSoapClient extends SoapClient{
function __doRequest($request, $location, $action, $version, $one_way = 0) {
$result = parent::__doRequest($request, $location, $action, $version);
$str = preg_replace('#<Discount xsi:type="ProgressivePromotion"(.+)type="(.+)"(.+)name="(.+)"/>#isU',
'<Discount xsi:type="ProgressivePromotion"$1type="wath ever"$3name="$2"/>', $result);
return $str;
}
}
您将在名称属性中找到折扣类型。因此,您必须实例化fixSoapClient
,而不是实例化SoapClient
您似乎正在使用具有名称空间意识的XML解析器解析响应,但解析器的名称空间支持没有打开。这会导致两个规则发生冲突。
- 在使用名称空间解析XML文档时,所有元素和属性都会使用其扩展名称进行引用。扩展名称由命名空间URI和元素/属性的本地名称组成。如果解析器不知道名称空间,那么名称的URI部分就会丢失。因此,如果没有打开命名空间支持,一些具有命名空间支持的解析器也会删除命名空间前缀
- 一个元素不允许包含两个具有相同(扩展)名称的属性。在这种情况下,另一个属性将丢失。通常,具有名称空间意识的XML解析器会将这两个
type
属性视为{http://www.w3.org/2001/XMLSchema-instance}type
和type
(使用James Clark表示法)。非命名空间感知解析器应该返回属性名称xsi:type
和type
。在这些情况下,没有名称冲突,一切都应该正常
如果您的解析器知道冒号:
可用作名称空间前缀分隔符,但解析器没有使用名称空间,因此丢弃了分隔符和名称空间前缀,则会出现问题。然后,这两个属性都将获得名称type
,而其中另一个属性由于属性名称唯一性规则而丢失/覆盖。
解决方案:为您的解析器设置命名空间支持,或者切换到另一个功能更强大的解析器。如果您使用有关如何解析XML文件的信息更新问题,希望有人能给出更具体的答案。