【问题标题】:How to add <![CDATA[ and ]]> in XML prepared by Jaxb如何在 Jaxb 准备的 XML 中添加 <![CDATA[ 和 ]]>
【发布时间】:2014-07-26 02:36:40
【问题描述】:

如何用 CDATA 准备 XML,

我正在通过 Jaxb 准备此响应,

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
 <SOAP-ENV:Header/>
 <soapenv:Body>
   <tem:RequestData>
     <tem:requestDocument>
        <![CDATA[
        <Request>
           <Authentication CMId="68" Function="1" Guid="5594FB83-F4D4-431F-B3C5-EA6D7A8BA795" Password="poihg321TR"/>
           <Establishment Id="4297867"/>
        </Request>
        ]]>
      </tem:requestDocument>
   </tem:RequestData>
 </soapenv:Body>
 </soapenv:Envelope>  

但是从 Jaxb 我没有得到 CDATA ,如何将 CDATA 放入 &lt;tem:requestDocument&gt; 元素中。

这是我的 Java 代码:

  public static String test1() {
    try {
        initJB();
        String response = null;
        StringBuffer xmlStr = null;
        String strTimeStamp = null;
        com.cultagent4.travel_republic.gm.Envelope envelope = null;
        com.cultagent4.travel_republic.gm.Header header = null;
        com.cultagent4.travel_republic.gm.Body body = null;
        com.cultagent4.travel_republic.gm.RequestData requestData = null;
        com.cultagent4.travel_republic.gm.RequestDocument requestDocument = null;
        com.cultagent4.travel_republic.gm.RequestDocument.Request request = null;
        com.cultagent4.travel_republic.gm.RequestDocument.Request.Authentication authentication = null;
        com.cultagent4.travel_republic.gm.RequestDocument.Request.Establishment establishment = null;

        ObjectFactory objFact = new ObjectFactory();
        envelope = objFact.createEnvelope();
        header = objFact.createHeader();
        envelope.setHeader(header);
        body = objFact.createBody();
        requestData = objFact.createRequestData();


        requestDocument = objFact.createRequestDocument();
        request = new RequestDocument.Request();

        authentication = new RequestDocument.Request.Authentication();
        authentication.setCMId("68");
        authentication.setGuid("5594FB83-F4D4-431F-B3C5-EA6D7A8BA795");
        authentication.setPassword("poihg321TR");
        authentication.setFunction("1");
        request.setAuthentication(authentication);
        establishment = new RequestDocument.Request.Establishment();
        establishment.setId("4297867");
        request.setEstablishment(establishment);
        requestDocument.setRequest(request);
        requestData.setRequestDocument(requestDocument);
        body.setRequestData(requestData);
        envelope.setBody(body);



        jaxbMarshallerForBase = jaxbContextForBase.createMarshaller();
        OutputStream os = new ByteArrayOutputStream();


        System.out.println();
        // output pretty printed

//                jaxbMarshallerForBase.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
//                jaxbMarshallerForBase.marshal(envelope, System.out);
//                jaxbMarshallerForBase.marshal(envelope, os);


        jaxbMarshallerForBase.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
        jaxbMarshallerForBase.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
//            jaxbMarshallerForBase.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, false);
// get an Apache XMLSerializer configured to generate CDATA
        XMLSerializer serializer = getXMLSerializer();


// marshal using the Apache XMLSerializer
        SAXResult result = new SAXResult(serializer.asContentHandler());

         System.out.println("*************");
        jaxbMarshallerForBase.marshal(envelope, result);
        System.out.println("--------------");



        return null;
    } catch (JAXBException ex) {
        Logger.getLogger(GM_TravelRepublic.class.getName()).log(Level.SEVERE, null, ex);
    } finally {
        return null;
    }
}

private static XMLSerializer getXMLSerializer() {
    // configure an OutputFormat to handle CDATA
    OutputFormat of = new OutputFormat();

    // specify which of your elements you want to be handled as CDATA.
    // The use of the ; '^' between the namespaceURI and the localname
    // seems to be an implementation detail of the xerces code.
    // When processing xml that doesn't use namespaces, simply omit the
    // namespace prefix as shown in the third CDataElement below.
    of.setCDataElements(new String[]{"^Request","^Authentication","^Establishment"});


    // set any other options you'd like
   of.setPreserveSpace(true);
    of.setIndenting(true);


    StringWriter writer = new StringWriter();
    // create the serializer
    XMLSerializer serializer = new XMLSerializer(of);


    serializer.setOutputByteStream(System.out);


    return serializer;
}  

在这里我得到相同的 xml,但没有 CDATA。我的服务器不接受没有 CDATA 的请求。请帮助。

【问题讨论】:

    标签: java xml jaxb cdata


    【解决方案1】:

    你能从中得出逻辑吗

    进口

    import org.dom4j.CDATA;
    import org.dom4j.DocumentHelper;
    

    示例代码

    public static String appendCdata(String input) {
        CDATA cdata = DocumentHelper.createCDATA(input);      
        return cdata.asXML();
    }
    

    【讨论】:

      【解决方案2】:
      1. 您需要创建一个扩展XMLAdapter 类的自定义适配器类。
      import javax.xml.bind.annotation.adapters.XmlAdapter;
      
      public class CDATAAdapter extends XmlAdapter<String, String> {
      
          @Override
          public String marshal(String inStr) throws Exception {
              return "<![CDATA[" + inStr + "]]>";
          }
      
          @Override
          public String unmarshal(String v) throws Exception {
              return inStr;
          }
      }
      
      1. 在您的 Java Bean 或 POJO 中,在 CDATA 所需的字符串上定义 XMLJavaTypeAdapter
      @XmlJavaTypeAdapter(value=CDATAAdapter.class)
      private String message;
      
      1. 默认情况下,JAXB RI 的编组器实现会尝试转义字符。为了改变这种行为,我们编写了一个类 实现CharacterEscapeHandler

      这个接口有一个转义方法,需要重写。

      import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler;
      
      m.setProperty("com.sun.xml.internal.bind.characterEscapeHandler",
                      new CharacterEscapeHandler() {
                          @Override
                          public void escape(char[] ch, int start, int length,
                                  boolean isAttVal, Writer writer)
                                  throws IOException {
                              writer.write(ch, start, length);
                          }
                      });
      

      其次,它也可以通过 Eclipse MOXy 实现来完成。

      【讨论】:

        【解决方案3】:

        CDATA 是字符数据,看起来您的服务器希望以 Request 开头的 XML 部分作为文本输入。创建XmlAdapterRequest 的实例转换为String 可能就足够了。生成的字符不会在 CDATA 中转义,但这可能适合您的用例。

        如果除了XmlAdapter 之外您真的需要它作为 CDATA,您可以应用以下链接中描述的策略之一:

        【讨论】:

          【解决方案4】:

          来自 Apache 文档中的 setCDataElements method description

          Sets the list of elements for which text node children should be output as CDATA.

          我认为这意味着,tem:requestDocument 元素的子元素都应该是单个文本块的一部分(而不是它们本身的 xml 元素),这样才能正常工作。完成后,可能很简单

          of.setCDataElements(new String[]{"tem^requestDocument"});
          

          应该可以解决问题。

          试试看告诉我:)

          【讨论】:

            【解决方案5】:

            我认为在您的 private static XMLSerializer getXMLSerializer() 方法中,您设置了错误的 CDATA 元素,因为您的 CDATA 元素是 &lt;tem:requestDocument&gt; 而不是 Request AuthenticationEstablishment 这是内容。尝试:

            of.setCDataElements(new String[]{"tem^requestDocument","http://tempuri.org/^requestDocument","requestDocument"});
            

            代替:

            of.setCDataElements(new String[]{"^Request","^Authentication","^Establishment"});
            

            希望对你有帮助,

            【讨论】:

            • 操作对不起@LMK。我确定这是方法,可能是我错误地指定了匹配的名称(我不记得确切的语法),尝试:of.setCDataElements(new String[]{"ns3^requestDocument","^requestDocument","ns3:requestDocument"});,我也更新了答案。希望这次对大家有帮助。
            【解决方案6】:

            您的服务器期望 &lt;tem:requestDocument&gt; 包含 文本,而不是 &lt;Request&gt; 元素。 CDATA 真的只是有助于创建手写 XML,因此您不必担心转义嵌入的 XML。事情是, JAXB 可以很好地处理转义,如果您的服务器是一个好的 XML 公民,它应该 将正确转义的 XML 与 CDATA 块中的 XML 相同。

            所以,不要在 requestDocument 中添加 request 元素 你在:

            requestDocument = objFact.createRequestDocument();
            request = new RequestDocument.Request();
            
            ...
            requestDocument.setRequest(request);
            

            您应该首先使用 JAXB 将 request 编组为正确转义的字符串 并将 that 设置为 requestDocument 值:

            requestDocument = objFact.createRequestDocument();
            request = new RequestDocument.Request();
            
            ...
            String escapedRequest = marshal(request);
            requestDocument.setRequest(escapedRequest);
            

            实现marshal(request) 留作练习。 ;)

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2014-10-07
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-03-10
              相关资源
              最近更新 更多