Parsing namespace from SOAPClient Response

心已入冬 提交于 2019-12-13 06:31:06

问题


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.

  1. 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.
  2. 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 and type (using James Clark notation). A non-namespace aware parser should return attribute names xsi:type and type. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!