使用PHP SoapClient类映射选项,其中WSDL包含具有相同名称的元素和complexType

时间:2010-09-24 04:15:03

标签: php soap wsdl soap-client

我遇到了一些包含元素和具有相同名称的complexType的不同WSDL文件。例如,http://soap.search.msn.com/webservices.asmx?wsdl有两个名为“SearchResponse”的实体:

在这种情况下,我无法弄清楚如何使用SoapClient()“classmaps”选项将这些实体正确映射到PHP类。

PHP手册说:

  

classmap选项可用于映射   一些WSDL类型到PHP类。这个   option必须是带有WSDL的数组   类型作为PHP类的键和名称   作为价值观。

不幸的是,由于有两个具有相同密钥的WSDL类型('SearchResponse'),我无法弄清楚如何区分两个SearchResponse实体并将它们分配给相应的PHP类。

例如,以下是示例WSDL的相关片段:

<xsd:complexType name="SearchResponse">
    <xsd:sequence>
        <xsd:element minOccurs="1" maxOccurs="1" name="Responses" type="tns:ArrayOfSourceResponseResponses"/>
    </xsd:sequence>
</xsd:complexType>

<xsd:element name="SearchResponse">
    <xsd:complexType>
        <xsd:sequence>
            <xsd:element minOccurs="1" maxOccurs="1" name="Response" type="tns:SearchResponse"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:element>

这里的PHP显然会无法正常工作,因为类映射键是相同的:

<?php $server = new SoapClient("http://soap.search.msn.com/webservices.asmx?wsdl", array('classmap' => array('SearchResponse' => 'MySearchResponseElement', 'SearchResponse' => 'MySearchResponseComplexType'))); ?>

在搜索解决方案时,我发现Java Web Services通过允许您为“Element”或“ComplexType”实体指定自定义后缀来处理此问题。

http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/docs/1.5/tutorial/doc/JAXBUsing4.html#wp149350

所以,现在我觉得没有办法用PHP的SoapClient做到这一点,但我很好奇是否有人可以提供任何建议。 FWIW,我无法编辑远程WDSL。

任何想法???

1 个答案:

答案 0 :(得分:7)

这不是我的头脑,但我认为你可以将两个SearchResponse类型映射到MY_SearchResponse并尝试抽象两者之间的差异。这很愚蠢,但是这样的事情可能会吗?

<?php
//Assuming SearchResponse<complexType> contains SearchReponse<element> which contains and Array of SourceResponses
//You could try abstracting the nested Hierarchy like so:
class MY_SearchResponse
{
   protected $Responses;
   protected $Response;

   /**
    * This should return the nested SearchReponse<element> as a MY_SearchRepsonse or NULL
    **/
   public function get_search_response()
   {
      if($this->Response && isset($this->Response))
      {
         return $this->Response; //This should also be a MY_SearchResponse
      }
      return NULL;
   }

   /**
    * This should return an array of SourceList Responses or NULL
    **/
   public function get_source_responses()
   {
      //If this is an instance of the top SearchResponse<complexType>, try to get the SearchResponse<element> and it's source responses
      if($this->get_search_response() && isset($this->get_search_response()->get_source_responses()))
      {
         return $this->get_search_response()->get_source_responses();
      }
      //We are already the nested SearchReponse<element> just go directly at the Responses
      elseif($this->Responses && is_array($this->Responses)
      {
         return $this->Responses;
      }
      return NULL;
   }
}

class MY_SourceResponse
{
  //whatever properties SourceResponses have
}

$client = new SoapClient("http:/theurl.asmx?wsdl", array('classmap' => array('SearchResponse' => 'MY_SearchResponse', 'SourceResponse' => 'MY_SourceResponse')));