改变php中的soap前缀

时间:2011-12-28 00:09:10

标签: php soap

我正在将.net的soap web服务重写为php。默认情况下,php给我的标签看起来像这样:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tempuri.org/"><SOAP-ENV:Header><ns1:FindAllCategories/></SOAP-ENV:Header><SOAP-ENV:Body><ns1:FindAllCategoriesResponse><ns1:FindAllCategoriesResult><ns1:ArtistCategoryDto>

等...

但我需要这个:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><FindAllCategoriesResponse xmlns="http://tempuri.org/"><FindAllCategoriesResult><ArtistCategoryDto>

这与这里的问题类似:PHP AND SOAP. Change envelope但是我不想像他那样破解它。此外,我正在创建一个将由现有的iphone应用程序使用的soap服务,而不是使用PHP来使用SoapClient来使用soap服务。 iPhone应用程序只解析原始xml,我现在无法更改iPhone应用程序。

2 个答案:

答案 0 :(得分:5)

重新阅读你想要的东西并在这里搜索php文档是我的解决方案和我做的几个假设

<强>假设

  • 如果我是正确的,你知道SOAP前缀本身不是问题(只要它是一致的,你就可以使用任何前缀)。
  • 我们需要为这个特定的Iphone应用程序创建一个解决方法,该应用程序使用当前无法修改/升级的(xml)解析器

你想要什么?

  1. 您希望使用本机API来更改SOAP前缀
  2. 您希望捕获SoapServer响应,以便在返回之前更改SOAP前缀
  3. <强>解决方案

    1. 目前没有用于更改SOAP前缀的本机SoapServer API方法
    2. 您可以通过regex或xml解析器捕获SoapServer响应并处理响应,请参阅下面的示例
    3. <?php
      
      // Create you parse function - Regex
      function SoapServerRegexParser($input)
      {
          // $input contains your XML Response
          // Do str_replace or preg_replace   
          $request = preg_replace({do replace});
      
          //return modified output to client
          return $request;
      }
      
      // OR create you parse function - Regex XML Parser
      function SoapServerXMLParser($input)
      {
          // $input contains your XML Response
          // Use any xml parser that you would like   
          $xml = new DOMDocument();
          $xml->formatOutput = true;
          $xml->preserveWhiteSpace = false;
          $xml->loadXML($input);
          //Do replacement have a looke at: DOMNode::replaceChild
      
          //return modified output to client
          return $xml->saveXML();
      }
      
      // Make php buffer all output
      // Send all output to a callBack function
      
      // Replace 'SoapServerRegexParser' with the callback function name of choice
      ob_start('SoapServerRegexParser'); //buffer output and set callback function
      
      // Create SoapServer
      $server = new SoapServer('wsdlfile.wsdl');
      $server->handle(); //Handle incoming request
      ob_end_flush(); //Release buffer, but send through callback function first
      
      ?>
      

      这应该可以解决问题,我没有创建正则表达式部分或实际的xlm节点替换,但我认为你可以自己做这个

答案 1 :(得分:1)

如果你不想使用正则表达式,我已经完成了这个快速类实现,它使用DomXPath和DomDocument来清理XML并在节点级别追加命名空间属性。

<?php

public BetterSoapClient extends SoapClient {

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

    public function __doRequest($request, $location, $action, $version) {

        $dom = new DOMDocument('1.0');

        // loads the SOAP request to the Document
        $dom->loadXML($request);

        // Create a XPath object
        $path = new DOMXPath($dom);

        // Search the nodes to fix
        $nodesToFix = $path->query('//SOAP-ENV:Envelope/SOAP-ENV:Body/*', null, true);

        // Remove unwanted namespaces
        $this->fixNamespace($nodesToFix, 'ns1', 'http://tempuri.org/');

        // Save the modified SOAP request
        $request = $dom->saveXML();

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

    public function fixNamespace(DOMNodeList $nodes, $namespace, $value) {
        // Remove namespace from envelope
        $nodes->item(0)
                ->ownerDocument
                ->firstChild
                ->removeAttributeNS($value, $namespace);

        //iterate through the node list and remove namespace

        foreach ($nodes as $node) {

            $nodeName = str_replace($namespace . ':', '', $node->nodeName);
            $newNode = $node->ownerDocument->createElement($nodeName);

            // Append namespace at the node level
            $newNode->setAttribute('xmlns', $value);

            // And replace former node
            $node->parentNode->replaceChild($newNode, $node);
        }
    }
}