问题
OK so I have SOAPClient making a call. If I use __getLastResponse() I get a line in my XML like this:
<Discount xsi:type="ProgressivePromotion" from="2013-05-05T00:00:00" to="2013-05-14T00:00:00" type="Percent" value="20" name="Special Deal"/>
However, the function in my SOAPClient Class returns an object.
The code for the call in the PHP class is:
function SearchHotels($parameters ){
$funcRet = null;
try {
$funcRet = $this->client->SearchHotels($parameters);
} catch ( Exception $e ) {
echo "(SearchHotels) SOAP Error:\n-------------------------------------\n" . $e->getMessage () . "\n\n";
echo "(SearchHotels) Request:\n-------------------------------------\n" . $this->client->__getLastRequest() . "\n\n";
echo "(SearchHotels) Response:\n-------------------------------------\n" . $this->client->__getLastResponse() . "\n\n";
}
return $funcRet;
}
When I use the object that is returned, I can access the following attributes from the Discount element as:
type: ProgressivePromotion
from: 2013-05-05T00:00:00
to: 2013-05-14T00:00:00
value: 20
name: Special Deal
But I can't access type="Percent"
It seems that SOAPClient disregards the xsi namespace in xsi:type and just stores that attribute as type.
So how can I access xsi:type AND type so I can tell if my discount is a Percent or Amount or whatever other type it could be?
BTW, at the top of my SOAP Response, I do not see ANYTHING declaring what xsi is.
<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">
EDIT
If I var_dump the object returned, I get
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
)
See how I lost the type="Amount"?
I can't call Discounts by doing
echo $result->SearchHotelsResult->HotelList->Hotel[0]->RoomTypes->RoomType[0]->Discounts->type;
Because I get
Undefined property: stdClass::$Discounts Notice: Trying to get property of non-object
So I convert the whole object into a giant multidimensional array and access things that way. Regardless, the type="Amount" isn't being pulled.
回答1:
i fixed the problem this way.
<?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;
}
}
You will find the discount type in the name attribute.
So instead of instantiate SoapClient
you have to instantiate fixSoapClient
回答2:
It seems like you are parsing your response with a namespace aware XML parser but the namespace support of the parser isn't turned on. This results in a clash of two rules.
- When parsing an XML document with namespaces, all elements and attributes are referred to with their expanded name. Expanded name consist of the namespace URI and the local name of the element/attribute. If the parser is not namespace aware, the URI part of the name is lost. Therefore some parsers with namespace support also drop the namespace prefix if the namespace support is not turned on.
- An element is not allowed to contain two attributes with same (expanded) name. In such cases other one of the attributes is lost. Normally a namespace aware XML parser would see those two
type
attributes as{http://www.w3.org/2001/XMLSchema-instance}type
andtype
(using James Clark notation). A non-namespace aware parser should return attribute namesxsi:type
andtype
. In these cases there is no name collision and everything should work ok.
Problems arise if your parser knows that a colon :
works as a namespace prefix delimiter but the parser is not using namespaces and therefore drops the delimiter and the namespace prefix. Then both of these attributes will get name type
and other one of these is lost/overwritten because of the attribute name uniqueness rule.
Solution: Set namespace support on for your parser or switch to another more capable parser. Hopefully someone can give more specific answers if you update your question with information on how the XML file is being parsed.
来源:https://stackoverflow.com/questions/14737719/parsing-namespace-from-soapclient-response