2011-12-28 32 views
9

estoy reescribiendo un servicio web de jabón de .net a php. Por defecto, PHP me está dando etiquetas que se ven así:cambiar prefijos de jabón en 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> 

etc ...

pero necesito esto:

<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> 

Esto es similar a la pregunta aquí: PHP AND SOAP. Change envelope embargo me gustaría no hackearlo de la forma en que lo hizo. Además, estoy creando un servicio de jabón que será consumido por una aplicación de iPhone existente, sin usar PHP para consumir un servicio de jabón usando SoapClient. La aplicación de iPhone solo analiza el xml sin procesar y no puedo cambiar la aplicación de iPhone en este momento.

+1

¿Puede decirnos qué específicamente no le gusta con la otra solución? ¿Dónde ves una falta? Además, "Simplemente necesito que esto funcione" es difícil de lograr, porque la aplicación de Iphone obviamente tiene una falla. Tal vez no sea el único, entonces, ¿cómo podría alguien responder a tu pregunta si no es solo adivinar? – hakre

+0

Claro. Entonces un par de problemas. Primero, estoy construyendo un servicio de soap, y el ejemplo es usar un soap client. No estoy usando ningún cliente de php soap, la aplicación es el cliente. En segundo lugar, no me gusta usar RegEx para hackear el xml.Prefiero hacerlo con alguna API nativa o, si es absolutamente necesario, usar un analizador xml para analizar los espacios de nombres, pero no sé cómo obtener una respuesta para analizar el XML. La aplicación definitivamente tiene un inconveniente, porque no está usando jabón de la manera en que fue diseñado. Pero es la forma en que fue construido porque no había buenos analizadores de jabón en ese momento. – fregas

Respuesta

5

Después de volver a leer qué es lo que quiere y buscar a través de la documentación de PHP aquí es mi solución y un par de suposiciones que hice

Supuestos

  • Si yo' Como es correcto, sabe que el prefijo SOAP no es el problema (puede usar cualquier prefijo, siempre que sea coherente).
  • Necesitamos crear un trabajo en torno a esta aplicación específica Iphone que hace uso de un analizador sintáctico (XML) que en la actualidad no puede ser modificado/actualizado por que

¿Qué desea?

  1. ¿Le gustaría utilizar una API nativa para alterar el prefijo de SOAP
  2. que se desea capturar la respuesta SoapServer para que pueda alterar el prefijo jabón antes de que se está volviendo

Solución

  1. Actualmente no existe un método API nativa SoapServer para alterar el prefijo de SOAP
  2. Usted puede coger la respuesta SoapServer y procesar la respuesta ya sea mediante expresiones regulares o xml parser véase el siguiente ejemplo
<?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 

?> 

Esto debe hacer el truco, no he creado la parte de expresiones regulares o la sustitución nodo xlm real pero creo que puede hacerlo usted mismo

+0

En realidad, necesito que los prefijos del espacio de nombres sean muy específicos. La aplicación de iPhone los está buscando. Sin embargo, si puedo cambiar la salida en el buffer de la manera en que lo haces aquí, creo que estoy bien. Entonces, en lugar de: ob_start ('SoapServerRegexParser'); Yo usaría: SoapServerXMLParser '); ... si quisiera analizarlo usando xml? – fregas

+0

Sí, eso es correcto. Eche un vistazo a http://nl2.php.net/manual/en/domnode.replacechild.php sobre cómo reemplazar un nodo hijo. Si las cadenas que está buscando y desea reemplazarlas, creo que es más fácil simplemente usar str_replace –

+0

Muy bien, justo lo que necesitaba para escribir rápidamente un servidor de soap flexible. – Olaf

0

Si no desea utilizar expresiones regulares, he hecho esta implementación de clase rápida que utiliza DomXPath y DomDocument para limpiar el XML y anexar el atributo de espacio de nombres en el nivel de nodo.

<?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

esto no me ayuda. Construyo un servicio web soap, usando SoapServer, sin consumir otro servicio usando SoapClient. He modificado la publicación original para que quede más claro, aunque originalmente lo mencioné y también en los comentarios. – fregas

Cuestiones relacionadas