题 在Java中从SOAPMessage获取原始XML


我在JAX-WS中设置了一个SOAP WebServiceProvider,但是我无法弄清楚如何从SOAPMessage(或任何Node)对象中获取原始XML。这是我现在所获得的代码示例,以及我试图获取XML的地方:

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

有没有一种简单的方法来获取原始请求的XML?如果有办法通过设置不同类型的Provider(例如Source)来获取原始XML,我也愿意这样做。


63
2018-02-06 22:04


起源




答案:


你可以试试这种方式。

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

137
2017-09-29 03:22



这不考虑字符编码 - artbristol
是否会像构建DOM对象等消耗大量内存?或者它是否真的从HTTP响应中提供原始字符串而无需在内部解析xml? - Ruslan


如果你有 SOAPMessage 要么 SOAPMessageContext,你可以使用 Transformer,通过将其转换为 Source 通过 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());

这将考虑编码,因此您的“特殊字符”不会被破坏。


17
2017-11-20 08:53



提供消耗内存消耗? - lospejos


事实证明,可以通过使用Provider <Source>以这种方式获取原始XML:

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

我最终不需要这个解决方案,所以我自己并没有真正尝试过这个代码 - 可能需要进行一些调整才能做到正确。但我知道这是从Web服务获取原始XML的正确途径。

(如果你绝对必须有一个SOAPMessage对象,我不确定如何使这个工作,但是如果你将要处理原始XML,那么为什么你会使用更高级别的对象呢?)


11
2018-02-25 19:00



一个 StringWriter 是一个很好的替代品 ByteArrayOutputStream+StreamResult 组合,如果你想将XML作为一个 String 使用正确的编码 - artbristol


仅用于调试目的,使用一行代码 -

msg.writeTo(System.out);


10
2017-09-11 09:42



OP不一定要调试System.out(Web服务器不一定方便访问) - 他/她可能需要通过套接字发送原始XML,将其存储在某个地方或计算其统计信息。 - Andrey Akhmetov
只是告诉一个选项,没有别的。谢谢 - Shahadat Hossain Khan
你可以轻松写入 ByteArrayOutputStream 转换成 String......对我来说似乎很容易 - vikingsteve


如果需要将xml字符串格式化为xml,请尝试以下操作:

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")));

5
2017-12-04 16:28



是否可以在空格和制表符之间进行选择以进行此格式化?顺便说一句,我知道没有标明标签。 - Philippe Gioseffi


使用变压器工厂: -

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();
    }

4
2018-06-22 20:10





这很有效

 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();

1
2018-04-13 12:32



更多的解释而不是代码转储会很好。 - Raidri
无需解释。 - Martin Kersten


如果您有客户端代码,那么您只需添加以下两行来获取XML请求/响应。这里 _call 是 org.apache.axis.client.Call

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

0
2018-06-17 15:20