How to add <![CDATA[ and ]]> in XML prepared by Jaxb

谁说我不能喝 提交于 2019-12-23 07:07:19

问题


How to prepare XML with CDATA ,

I am preraring this response via 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>  

But from Jaxb i am not getting CDATA , how to put CDATA inside <tem:requestDocument> element.

Here is my Java Code :

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

Here I am getting same xml , but without CDATA. My server is not accepting the request without CDATA.Please help.


回答1:


  1. You need to create an custom adapter class which extends the XMLAdapter class.

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

public class CDATAAdapter extends XmlAdapter {

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

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

}

  1. Inside your Java Bean or POJO define XMLJavaTypeAdapter on the string required in CDATA

    @XmlJavaTypeAdapter(value=CDATAAdapter.class) private String message;

  2. By default, the marshaller implementation of the JAXB RI tries to escape characters. To change this behaviour we write a class that implements the CharacterEscapeHandler.

This interface has an escape method that needs to be overridden.

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

Secondly, it cn also be done via Eclipse MOXy implementation.




回答2:


Can you make the logic from this

imports

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

sample code

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



回答3:


CDATA is character data, it looks like your server wants the part of the XML starting with Request to come in as text. It may be enough for you to create an XmlAdapter to convert the instance of Request to a String. The resulting characters will be escaped not in CDATA but this May fit your use case.

Then if you really need it as CDATA in addition to the XmlAdapter you can apply one of the strategies described in the link below:

  • How to generate CDATA block using JAXB?



回答4:


From the setCDataElements method description in the Apache docs :

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

What I think that means is, the children of the tem:requestDocument element should all be part of one single text chunk (and not xml elements by themselves) in order for this to work. Once you've done that, probably a simple

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

should do the trick.

Try it and let me know :)




回答5:


I think that in your private static XMLSerializer getXMLSerializer() method you are setting wrong the CDATA elements, because your CDATA element is <tem:requestDocument> instead of Request Authentication and Establishment which are the content. Try with:

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

instead of:

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

Hope this helps,




回答6:


Your server is expecting <tem:requestDocument> to contain text, and not a <Request> element. CDATA is really just helpful for creating hand-written XML so you don't have to worry about escaping embedded XML. The thing is, JAXB handles escaping just fine and if your server is a good XML citizen it should treat properly escaped XML the same as XML in a CDATA block.

So, instead of adding a request element inside your requestDocument like you do in:

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

...
requestDocument.setRequest(request);

You should first use JAXB to marshal request into a properly escaped String and set that sa the requestDocument value:

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

...
String escapedRequest = marshal(request);
requestDocument.setRequest(escapedRequest);

Implementing marshal(request) is left as an exercise. ;)



来源:https://stackoverflow.com/questions/24054469/how-to-add-cdata-and-in-xml-prepared-by-jaxb

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!