在 Java 中从 SOAPMessage 获取原始 XML

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/522395/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 15:46:38  来源:igfitidea点击:

Getting Raw XML From SOAPMessage in Java

javasoapjax-ws

提问by Dan Lew

I've set up a SOAP WebServiceProvider in JAX-WS, but I'm having trouble figuring out how to get the raw XML from a SOAPMessage (or any Node) object. Here's a sample of the code I've got right now, and where I'm trying to grab the XML:

我已经在 J​​AX-WS 中设置了一个 SOAP WebServiceProvider,但是我无法弄清楚如何从 SOAPMessage(或任何节点)对象获取原始 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?
    }
}

Is there a simple way to get the XML of the original request? If there's a way to get the raw XML by setting up a different type of Provider (such as Source), I'd be willing to do that, too.

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

采纳答案by Dan Lew

It turns out that one can get the raw XML by using Provider<Source>, in this way:

事实证明,可以通过使用 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;
    }
}

I've ended up not needing this solution, so I haven't actually tried this code myself - it might need some tweaking to get right. But I know this is the right path to go down to get the raw XML from a web service.

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

(I'm not sure how to make this work if you absolutely must have a SOAPMessage object, but then again, if you're going to be handling the raw XML anyways, why would you use a higher-level object?)

(如果您绝对必须有一个 SOAPMessage 对象,我不确定如何使这项工作起作用,但话说回来,如果您无论如何都要处理原始 XML,为什么要使用更高级别的对象?)

回答by Smith Torsahakul

You could try in this way.

你可以试试这个方法。

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

回答by Hari

If you need formatting the xml string to xml, try this:

如果您需要将 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")));

回答by artbristol

If you have a SOAPMessageor SOAPMessageContext, you can use a Transformer, by converting it to a Sourcevia DOMSource:

如果您有SOAPMessageor SOAPMessageContext,则可以Transformer通过将其转换为Sourcevia来使用 a 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());

This will take the encoding into account, so your "special characters" won't get mangled.

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

回答by Shahadat Hossain Khan

for just debugging purpose, use one line code -

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

msg.writeTo(System.out);

msg.writeTo(System.out);

回答by ARIJIT

if you have the client code then you just need to add the following two lines to get the XML request/response. Here _callis org.apache.axis.client.Call

如果您有客户端代码,那么您只需要添加以下两行即可获取 XML 请求/响应。这_callorg.apache.axis.client.Call

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

回答by Sireesh Yarlagadda

Using Transformer Factory:-

使用变压器工厂:-

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

回答by user2900572

this works

这有效

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

回答by Oguz Demir

It is pretty old thread but recently i had a similar issue. I was calling a downstream soap service, from a rest service, and I needed to return the xml response coming from the downstream server as is.

这是很旧的线程,但最近我遇到了类似的问题。我正在从休息服务调用下游soap服务,我需要按原样返回来自下游服务器的xml响应。

So, i ended up adding a SoapMessageContext handler to get the XML response. Then i injected the response xml into servlet context as an attribute.

所以,我最终添加了一个 SoapMessageContext 处理程序来获取 XML 响应。然后我将响应 xml 作为属性注入到 servlet 上下文中。

public boolean handleMessage(SOAPMessageContext context) {

            // Get xml response
            try {

                ServletContext servletContext =
                        ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getServletContext();

                SOAPMessage msg = context.getMessage();

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

                servletContext.setAttribute("responseXml", strMsg);

                return true;
            } catch (Exception e) {
                return false;
            }
        }

Then I have retrieved the xml response string in the service layer.

然后我在服务层检索了xml响应字符串。

ServletContext servletContext =
                ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getServletContext();

        String msg = (String) servletContext.getAttribute("responseXml");

Didn't have chance to test it yet but this approach must be thread safe since it is using the servlet context.

还没有机会测试它,但这种方法必须是线程安全的,因为它使用 servlet 上下文。