问题
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:
- 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;
}
}
Inside your Java Bean or POJO define XMLJavaTypeAdapter on the string required in CDATA
@XmlJavaTypeAdapter(value=CDATAAdapter.class) private String message;
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