草庐IT

PHP SoapClient 不处理 WSDL 中的抽象和替换组属性

coder 2023-06-15 原文

我正在使用他们提供的 wsdl 向加拿大邮政发送调用,其中包含如下部分:

<!-- group-id and transmit-shipment are mutually exclusive -->
<xsd:element name="groupIdOrTransmitShipment" abstract="true" />
<xsd:element name="group-id" type="tns:GroupIDType" substitutionGroup="tns:groupIdOrTransmitShipment"/>
<xsd:element name="transmit-shipment" type="xsd:boolean" fixed="true" substitutionGroup="tns:groupIdOrTransmitShipment"/>

<xsd:complexType name="ShipmentType">
    <xsd:all>
        <xsd:element ref="tns:groupIdOrTransmitShipment" />
        <xsd:element name="quickship-label-requested" type="xsd:boolean" minOccurs="0"/>
        <xsd:element name="cpc-pickup-indicator" type="xsd:boolean" fixed="true" minOccurs="0"/>
        <xsd:element name="requested-shipping-point" type="tns:PostalCodeType" minOccurs="0"/>
        <xsd:element name="shipping-point-id" type="tns:OutletIDType" minOccurs="0" />
        <xsd:element name="expected-mailing-date" type="xsd:date" minOccurs="0"/>
        <xsd:element name="delivery-spec" type="tns:DeliverySpecType"/>
        <xsd:element name="return-spec" type="tns:ReturnSpecType" minOccurs="0"/>
    </xsd:all>
</xsd:complexType>

在他们的代码示例中,他们扩展了 Soap 类并覆盖了 __doRequest()像这样的 SOAP 方法:

/*
 Need to override SoapClient because the abstract element 'groupIdOrTransmitShipment' is expected to be in the request in order for validation to pass.
So, we give it what it expects, but in __doRequest we modify the request by removing the abstract element and add the correct element.

*/

class MySoapClient extends SoapClient {

    function __construct($wsdl, $options = null) {
        parent::__construct($wsdl, $options);
    }

    function __doRequest($request, $location, $action, $version, $one_way = NULL) {
        $dom = new DOMDocument('1.0');
        $dom->loadXML($request);
        //get element name and values of group-id or transmit-shipment.
        $groupIdOrTransmitShipment =  $dom->getElementsByTagName("groupIdOrTransmitShipment")->item(0);
        $element = $groupIdOrTransmitShipment->firstChild->firstChild->nodeValue;
        $value = $groupIdOrTransmitShipment->firstChild->firstChild->nextSibling->firstChild->nodeValue;

        //remove bad element
        $newDom = $groupIdOrTransmitShipment->parentNode->removeChild($groupIdOrTransmitShipment);

        //append correct element with namespace
        $body =  $dom->getElementsByTagName("shipment")->item(0);
        $newElement = $dom->createElement($element, $value);
        $body->appendChild($newElement);

        //save $dom to string
        $request = $dom->saveXML();
        //echo $request;

        //doRequest
        return parent::__doRequest($request, $location, $action, $version);
    }
}

使用他们的重写方法可以正常工作,因为它会改变 xml 请求,但让我感到非常困惑的是为什么他们这样做。 WSDL 有什么根本性的错误吗?这是 PHP 的 SoapClient 中的错误吗?我想要一种发送有效请求而不覆盖任何核心类方法的方法。

据我了解,作者想要一个 group-id transmit-shipment元素,但不能两者兼而有之。因为你不能有 <choice> <all> 中的元素元素,根据 this discussion on w3c.org , 为此目的声明一个替换组并且在我的请求中只包含两个元素之一应该没问题,但如果我只包含 transmit-shipment并省略抽象元素 groupIdOrTransmitShipment php 返回错误:

SOAP-ERROR: Encoding: object has no 'groupIdOrTransmitShipment' property

更新: 这很旧,但它是否相关? https://bugs.php.net/bug.php?id=48570

最佳答案

我也不得不覆盖和扩展 php SoapClass。它与 php soapclass 有关,它在请求/响应中期望某种格式,然后是接收/发送的内容。扩展它允许我自己处理格式。

wsdl 没有问题,错误是类的一部分。没有办法绕过覆盖

关于PHP SoapClient 不处理 WSDL 中的抽象和替换组属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34211471/

有关PHP SoapClient 不处理 WSDL 中的抽象和替换组属性的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  3. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  4. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  5. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  6. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  7. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  8. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  9. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  10. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

随机推荐