【问题标题】:CDATA element in WSDL clientWSDL 客户端中的 CDATA 元素
【发布时间】:2016-10-21 17:06:42
【问题描述】:

我正在做一个 WSDL 客户端,想知道如何将 XML 元素设置为 CDATA。

我使用wsimport 来生成源代码,而CDATA 元素是请求XML 的一部分。 这是请求的 XML 类:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = { "dataRequest" }) 
@XmlRootElement(name = "ProcessTransaction")
public class ProcessTransaction {

    protected String dataRequest;

    public String getDataRequest() {
        return dataRequest;
    }

    public void setDataRequest(String value) {
        this.dataRequest = value;
    }  
} 

我已经尝试过@XmlAdapter,但它对输出没有任何改变...

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class AdaptorCDATA extends XmlAdapter<String, String> {

    @Override
    public String marshal(String arg0) throws Exception {
        return "<![CDATA[" + arg0 + "]]>";
    }

    @Override
    public String unmarshal(String arg0) throws Exception {
        return arg0;
    }
}

在 XML 类中:

@XmlJavaTypeAdapter(value=AdaptorCDATA.class)
protected String dataRequest;

我尝试调试,但它从未踩到AdaptorCDATA 函数。

wsimport 版本是2.2.9jaxb-api 版本是2.1

【问题讨论】:

  • 为什么需要这个?因为您想将 xml-data 写入元素?这应该是开箱即用的。我们有一个 xml-data 字符串,将其设置为相应元素中的值,然后 JAXB 的魔法在编组时将 CDATA 包装在四周。
  • 我需要这个,因为当我使用 CDATA 字符串设置“dataRequest”时,它会被完全转义。
  • 好的,我刚刚用我们的一个类的任意字符串成员尝试了你的 AdaptorCDATA,它很好地进入了marshall()-方法。看着你的问题,我看到你有一个 sn-p,你有 @XmlJavaTypeAdapter-Annotation 但不在应该在的 ProcessTransaction-class 中。如果你有它但是断点仍然没有命中,也许你必须在启动客户端之前重建和刷新?
  • 你没有为 marshaller 设置 CharacterEscapeHandler,这就是你让所有 CDATA 转义的原因。检查stackoverflow.com/a/14197860/1516873 的其余部分并且AFAIK wsimport 不支持为客户端设置marshaller 属性。 CXF客户端支持cxf.apache.org/docs/jaxb.html

标签: java xml jaxb wsdl wsimport


【解决方案1】:

因此,正如@user1516873 建议的那样,我将代码移至 cxf,并且运行良好。现在我正在使用“wsdl2java”来生成代码,以及我项目中来自 cxf 的 jars。

代码有什么不同:

CdataInterceptor

import javax.xml.stream.XMLStreamWriter;

import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;

public class CdataInterceptor extends AbstractPhaseInterceptor<Message> {

    public CdataInterceptor() {
        super(Phase.MARSHAL);
    }

    public void handleMessage(Message message) {
        message.put("disable.outputstream.optimization", Boolean.TRUE);
        XMLStreamWriter writer = (XMLStreamWriter) message.getContent(XMLStreamWriter.class);
        if (writer != null && !(writer instanceof CDataContentWriter)) {
            message.setContent(XMLStreamWriter.class, new CDataContentWriter(writer));
        }
    }

    public void handleFault(Message messageParam) {
        System.out.println(messageParam);
    }
}

CDataContentWriter

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

import org.apache.cxf.staxutils.DelegatingXMLStreamWriter;

public class CDataContentWriter extends DelegatingXMLStreamWriter {

    public CDataContentWriter(XMLStreamWriter writer) {
        super(writer);
    }

    public void writeCharacters(String text) throws XMLStreamException {
        boolean useCData = text.contains("RequestGeneric");
        if (useCData) {
            super.writeCData(text);
        } else {
            super.writeCharacters(text);
        }
    }

    // optional 
    public void writeStartElement(String prefix, String local, String uri) throws XMLStreamException {
        super.writeStartElement(prefix, local, uri);
    }
}

使用编写器和拦截器:

MyService wcf = new MyService(url, qName);
IMyService a = wcf.getBasicHttpBinding();

Client cxfClient = ClientProxy.getClient(a);
CdataInterceptor myInterceptor = new CdataInterceptor();
cxfClient.getInInterceptors().add(myInterceptor);
cxfClient.getOutInterceptors().add(myInterceptor);

而且效果很好!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-30
    • 1970-01-01
    • 2013-09-22
    • 1970-01-01
    • 2010-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多