更改肥皂在php中的前缀

问题描述:

我正在从.net到PHP重写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我不想像他那样破解它。另外,我正在创建一个soap服务,它将被现有的iPhone应用程序使用,而不是使用PHP来使用SoapClient使用soap服务。 iPhone应用程序只是解析原始的XML,我现在不能改变iPhone应用程序。

+1

你能告诉你有什么特别的不喜欢与其他解决方案?你在哪里看到短缺?另外“我只是需要这个工作”很难完成,因为Iphone App显然有一个缺点。也许它不是唯一的一个,那么如果没有猜测的话,一个人怎么回答你的问题呢? – hakre 2011-12-30 20:58:10

+0

当然。所以有几个问题。首先,我正在构建一个soap服务,并且该示例使用了一个soap客户端。我根本不使用php soap客户端 - 该应用程序是客户端。其次,我不喜欢使用RegEx来破解xml。我宁愿用一些本地api来实现,或者如果绝对必要的话,使用xml解析器来解析名称空间,但我不知道如何获得解析XML的响应。 该应用程序肯定有一个缺点,因为它不按照它的意图使用肥皂。但它的构建方式是因为当时没有好的解析器。 – fregas 2012-01-03 16:17:30

重新阅读它是什么,你想通过PHP文档这里搜索后是我的解决方案和一对夫妇的假设,我提出

假设

  • 如果我m正确你知道SOAP前缀本身不是问题(只要它是一致的,你可以使用任何前缀)。
  • 我们需要对各地工作创造了这个特定的iPhone应用程序,使用了一个(XML)解析器,目前不能被修改/被你升级

你想做什么?

  1. 您想使用原生API改变SOAP前缀
  2. 你想赶上SoapServer的响应,因此您可以改变SOAP前缀返回

解决方案之前,

  1. 目前没有改变SOAP前缀没有本地SoapServer的API方法
  2. 您可以赶上SoapServer的响应和处理或者通过正则表达式或XML解析器响应见下文
<?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节点更换但我想你可以自己做

+0

实际上,我确实需要命名空间前缀才能非常具体。 iPhone应用程序正在寻找他们。但是,如果我可以按照你在这里所做的方式更改缓冲区中的输出,我认为我很好。因此而不是: ob_start('SoapServerRegexParser'); 我会用:SoapServerXMLParser'); ...如果我想用xml解析它? – fregas 2012-01-06 22:09:58

+0

是的,这是正确的。看看http://nl2.php.net/manual/en/domnode.replacechild.php关于如何替换一个子节点。如果您正在搜索的字符串,并且您想要替换它们,我认为只需使用str_replace – 2012-01-07 09:55:16

+0

非常酷 - 我需要快速编写一个灵活的soap服务器。 – Olaf 2016-08-23 13:27:02

如果您不想使用正则表达式,我已经完成了这个快速的类实现,它使用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); 
     } 
    } 
} 
+0

这不帮助我。我使用SoapServer构建soap web服务,而不是使用SoapClient使用另一个服务。我修改了原来的帖子,使其更加清晰,尽管我最初提到了它,并且也在评论中提到了它。 – fregas 2012-01-04 19:46:56