2009-02-06 30 views
58

He configurado un SOAP WebServiceProvider en JAX-WS, pero tengo problemas para averiguar cómo obtener el XML sin formato desde un objeto SOAPMessage (o cualquier nodo). He aquí un ejemplo del código que tengo en este momento, y donde yo estoy tratando de agarrar el XML:Obtención de XML sin formato desde SOAPMessage en Java

@WebServiceProvider(wsdlLocation="SoapService.wsdl") 
@ServiceMode(value=Service.Mode.MESSAGE) 
public class SoapProvider implements Provider<SOAPMessage> 
{ 
    public SOAPMessage invoke(SOAPMessage msg) 
    { 
     // How do I get the raw XML here? 
    } 
} 

¿Hay una forma sencilla de obtener el código XML de la solicitud original? Si hay una forma de obtener el XML sin procesar configurando un tipo diferente de Proveedor (como Fuente), estaría dispuesto a hacerlo también.

Respuesta

11

Resulta que uno puede obtener el código XML sin procesar mediante el uso de Proveedor < Fuente>, de esta manera:

import java.io.ByteArrayOutputStream; 
import javax.xml.transform.Source; 
import javax.xml.transform.Transformer; 
import javax.xml.transform.TransformerFactory; 
import javax.xml.transform.stream.StreamResult; 
import javax.xml.ws.Provider; 
import javax.xml.ws.Service; 
import javax.xml.ws.ServiceMode; 
import javax.xml.ws.WebServiceProvider; 

@ServiceMode(value=Service.Mode.PAYLOAD) 
@WebServiceProvider() 
public class SoapProvider implements Provider<Source> 
{ 
    public Source invoke(Source msg) 
    { 
     StreamResult sr = new StreamResult(); 

     ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     sr.setOutputStream(out); 

     try { 
      Transformer trans = TransformerFactory.newInstance().newTransformer(); 
      trans.transform(msg, sr); 

      // Use out to your heart's desire. 
     } 
     catch (TransformerException e) { 
      e.printStackTrace(); 
     }  

     return msg; 
    } 
} 

he terminado no necesitar esta solución, así que en realidad no han probado este codificarme a mí mismo, podría necesitar algunos ajustes para hacerlo bien. Pero sé que este es el camino correcto para bajar para obtener el XML sin formato de un servicio web.

(No estoy seguro de cómo hacer que esto funcione si es absolutamente necesario tener un objeto SOAPMessage, pero de nuevo, si va a manejar el XML sin procesar de todos modos, ¿por qué usaría un objeto de nivel superior? ?)

+0

Un 'StringWriter' es una buena alternativa a la' 'ByteArrayOutputStream' + StreamResult' combinación, si quiere el XML como 'Cadena' con la codificación correcta – artbristol

131

Puede intentarlo de esta manera.

SOAPMessage msg = messageContext.getMessage(); 
ByteArrayOutputStream out = new ByteArrayOutputStream(); 
msg.writeTo(out); 
String strMsg = new String(out.toByteArray()); 
+4

Esto es increíble. – user85155

+3

Esto no tiene en cuenta la codificación de caracteres – artbristol

+0

¿Va a consumir mucha memoria con algo así como construir objetos DOM o similares? ¿O realmente dará la cadena cruda de la respuesta HTTP sin analizar internamente el xml? – Ruslan

4

Si necesita formatear la cadena XML a XML, intente esto:

String xmlStr = "your-xml-string"; 
Source xmlInput = new StreamSource(new StringReader(xmlStr)); 
Transformer transformer = TransformerFactory.newInstance().newTransformer(); 
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); 
transformer.transform(xmlInput, 
     new StreamResult(new FileOutputStream("response.xml"))); 
14

Si usted tiene un SOAPMessage o SOAPMessageContext, se puede utilizar un Transformer, mediante la conversión a un Source través DOMSource:

  final SOAPMessage message = messageContext.getMessage(); 
      final StringWriter sw = new StringWriter(); 

      try { 
       TransformerFactory.newInstance().newTransformer().transform(
        new DOMSource(message.getSOAPPart()), 
        new StreamResult(sw)); 
      } catch (TransformerException e) { 
       throw new RuntimeException(e); 
      } 

      // Now you have the XML as a String: 
      System.out.println(sw.toString()); 

Esto tendrá en cuenta la codificación, por lo que sus "caracteres especiales" no se romperán.

+0

¿Se proporciona una solución que consume memoria? – lospejos

8

para fines de depuración simplemente, utilizar una línea de código -

msg.writeTo(System.out);

+0

El OP no está necesariamente depurando al sistema.out (que no es necesariamente accesible para un servidor web): es posible que necesite enviar el XML original por un socket, almacenarlo en algún lugar o calcular sus estadísticas. – hexafraction

+1

simplemente hablando de una opción, nada más. gracias –

+0

Puede escribir fácilmente en un 'ByteArrayOutputStream' convertir a' String' ... me parece fácil – vikingsteve

0

si tiene el código de cliente a continuación, sólo tiene que añadir las dos líneas siguientes para obtener la solicitud XML/respuesta. Aquí es _callorg.apache.axis.client.Call

String request = _call.getMessageContext().getRequestMessage().getSOAPPartAsString(); 
String response = _call.getMessageContext().getResponseMessage().getSOAPPartAsString(); 
3

Usando fábrica de transformadores: -

public static String printSoapMessage(final SOAPMessage soapMessage) throws TransformerFactoryConfigurationError, 
      TransformerConfigurationException, SOAPException, TransformerException 
    { 
     final TransformerFactory transformerFactory = TransformerFactory.newInstance(); 
     final Transformer transformer = transformerFactory.newTransformer(); 

     // Format it 
     transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
     transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); 

     final Source soapContent = soapMessage.getSOAPPart().getContent(); 

     final ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); 
     final StreamResult result = new StreamResult(streamOut); 
     transformer.transform(soapContent, result); 

     return streamOut.toString(); 
    } 
1

esto funciona

final StringWriter sw = new StringWriter(); 

try { 
    TransformerFactory.newInstance().newTransformer().transform(
     new DOMSource(soapResponse.getSOAPPart()), 
     new StreamResult(sw)); 
} catch (TransformerException e) { 
    throw new RuntimeException(e); 
} 
System.out.println(sw.toString()); 
return sw.toString(); 
+0

Algunas explicaciones más en lugar de un volcado de código serían buenas. – Raidri

+0

No se necesita explicación. –

Cuestiones relacionadas