Xml 从SOAPClient响应解析命名空间

Xml 从SOAPClient响应解析命名空间,xml,soap,xml-namespaces,soap-client,Xml,Soap,Xml Namespaces,Soap Client,好的,我让SOAPClient打电话。如果我使用uu 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打电话。如果我使用uu 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"/>
使用返回的对象时,我可以从折扣元素访问以下属性:

类型:渐进式促销
起始日期:2013-05-05T00:00:00
致:2013-05-14T00:00:00
值:20
名称:特价

但我无法访问type=“Percent”

SOAPClient似乎忽略了xsi:type中的xsi名称空间,而只是将该属性存储为type

那么,我如何访问xsi:type和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">
查看我如何丢失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;
    }   
}

似乎您正在使用一个名称空间感知的XML解析器解析您的响应,但是该解析器的名称空间支持没有打开。这会导致两条规则发生冲突

  • 当使用名称空间解析XML文档时,所有元素和属性都会使用其扩展名称引用。扩展名称由名称空间URI和元素/属性的本地名称组成。如果解析器不知道名称空间,则名称的URI部分将丢失。因此,如果未启用名称空间支持,一些具有名称空间支持的解析器也会删除名称空间前缀
  • 元素不允许包含具有相同(扩展)名称的两个属性。在这种情况下,另一个属性将丢失。通常,支持名称空间的XML解析器会将这两个
    type
    属性视为
    {http://www.w3.org/2001/XMLSchema-instance}键入
    键入
    (使用詹姆斯·克拉克符号)。非名称空间感知解析器应该返回属性名
    xsi:type
    type
    。在这些情况下,没有名称冲突,一切正常
  • 如果解析器知道冒号
    用作名称空间前缀分隔符,但解析器未使用名称空间,因此会删除分隔符和名称空间前缀,则会出现问题。然后,这两个属性都将获得name
    type
    ,其中一个属性由于属性名称唯一性规则而丢失/覆盖


    解决方案:为您的解析器设置名称空间支持,或者切换到另一个功能更强大的解析器。如果您使用有关XML文件解析方式的信息更新您的问题,希望有人能给出更具体的答案。

    xsi
    就在第二行声明:
    xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance“
    。您能提供访问这些属性所使用的代码吗?这是一个命名空间问题,客户端对“”一无所知,认为有两个“类型”属性,并使用最后一个。您是否向您的客户机提供了wsdl?如果不是,那么应该在构造函数的参数数组中显式指定名称空间。您的示例将name=替换为ProgressivePromotion,而不是实际名称(“特价”),为了使这更复杂,还可能添加了其他属性,例如pay=和stay=No,xsi:type始终是“ProgressivePromotion”(它是ComplexType)。如果您还需要name属性,那么,例如,您可以保留name属性值+'#',然后保留折扣类型值,如name=“Special Deal#Percent”,然后按#分割(并且name和type都有),您不能添加额外的属性,因为内部解析器将使用xsd检查xml(由于xsd没有定义额外的属性,它们将无法识别).但我认为你有这个想法,-这是可行的,也是可以接受的,但我想看看是否有人可以在我提供赏金之前分享如何获取实际属性。这个问题可以帮助很多处理名称空间问题的人。这是内部解析器中的一个bug,提供的解决方案并不是很糟糕(这是一个破解,但很好)。解决此问题的唯一其他选项是使用第三方SoapCient。XML文件是如何解析的?我不明白。我正在使用上述SOAPClient。还有其他方法吗?
    Undefined property: stdClass::$Discounts  Notice: Trying to get property of non-object
    
    <?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;
        }   
    }