i'm rewriting a soap web service from .net to php. by default, php is giving me tags that look like this:
<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>
etc...
but i need this:
<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>
This is similar to the question here: PHP AND SOAP. Change envelope however i'd like to not hack it the way he did. Also, i am creating a soap service that will be consumed by an existing iphone app, not using PHP to consume a soap service using SoapClient. The iphone app just parses the raw xml and i can't change the iphone app right now.
After re-reading what it is you want and searching through the php documentation here is my solution and a couple of assumptions that I made
Assumptions
What do you want?
Solution
<?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
?>
This should do the trick, I haven't created the regex part or the actual xlm node replacement but I figure you can do that yourself
If you don't want to use Regular expressions, I've done this quick class implementation which uses DomXPath and DomDocument to cleanup the XML and append the namespace attribute at the node level.
<?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);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With