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

6

12

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.

Wahhabi answered 5/6, 2014 at 7:45 Comment(0)
O
6

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();
}
Obduliaobdurate answered 15/9, 2014 at 11:25 Comment(0)
M
6
  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<String, String> {

    @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;
  1. 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.

Maryannmaryanna answered 16/9, 2014 at 10:8 Comment(0)
I
1

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:

Increase answered 14/9, 2014 at 10:49 Comment(0)
O
0

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,

Observable answered 10/9, 2014 at 13:11 Comment(1)
Ops sorry @LMK. I'm sure that this is the way, may be I was wrong specifying the matching names (I don't remember the exact syntax), try with: of.setCDataElements(new String[]{"ns3^requestDocument","^requestDocument","ns3:requestDocument"});, I also update the answer. I hope that this time it's more helpful.Observable
S
0

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 :)

Spend answered 14/9, 2014 at 13:24 Comment(0)
C
0

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

Collbaith answered 17/9, 2014 at 0:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.