Как добавить <! [CDATA [и]]> в XML, подготовленный Jaxb

Как подготовить XML с CDATA,

Я использую этот ответ через 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 внутри элемента <tem:requestDocument>.

Вот мой код 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. Пожалуйста, помогите.

Ответ 1

Можете ли вы сделать логику из этого

импорт

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

пример кода

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

Ответ 2

  • Вам нужно создать собственный класс адаптера, который расширяет класс XMLAdapter.

импортировать javax.xml.bind.annotation.adapters.XmlAdapter;

Открытый класс CDATAAdapter расширяет XmlAdapter {

@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 определите XMLJavaTypeAdapter в строке, требуемой в CDATA

    @XmlJavaTypeAdapter (value = CDATAAdapter.class) личное сообщение String;

  2. По умолчанию реализация маршаллера JAXB RI пытается избежать символов. Чтобы изменить это поведение, напишем класс, который реализует CharacterEscapeHandler.

Этот интерфейс имеет метод escape, который необходимо переопределить.

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

Во-вторых, cn также можно выполнить с помощью реализации Eclipse MOXy.

Ответ 3

CDATA - это символьные данные, похоже, что ваш сервер хочет, чтобы часть XML, начиная с Request, появилась в виде текста. Вам может быть достаточно создать XmlAdapter, чтобы преобразовать экземпляр Request в String. Полученные символы будут экранированы не в CDATA, но это может соответствовать вашему варианту использования.

Затем, если вы действительно нуждаетесь в этом как CDATA в дополнение к XmlAdapter, вы можете применить одну из стратегий, описанных в ссылке ниже:

Ответ 4

Я думаю, что в вашем методе private static XMLSerializer getXMLSerializer() вы устанавливаете неправильные элементы CDATA, потому что ваш CDATA элемент <tem:requestDocument> вместо Request Authentication и Establishment, которые являются содержимым. Попробуйте:

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

вместо:

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

Надеюсь, что это поможет,

Ответ 5

Из описания setCDataElements в документах Apache:

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

Я думаю, что это означает, что дети элемента tem:requestDocument должны быть частью одного текстового фрагмента (а не элементов xml сами по себе), чтобы это работало. Как только вы это сделали, возможно, просто

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

должен сделать трюк.

Попробуйте и дайте мне знать:)

Ответ 6

Ваш сервер ожидает, что <tem:requestDocument> будет содержать текст, а не a <Request>. CDATA действительно полезен для создания рукописных XML, так что вам не нужно беспокоиться об экранировании встроенного XML. Дело в том, JAXB отлично справляется с экранированием, и если ваш сервер является хорошим гражданином XML, он должен обрабатывать правильно экранированный XML так же, как XML в блоке CDATA.

Итак, вместо добавления элемента запроса внутри вашего запросаDocument, например вы делаете в:

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

...
requestDocument.setRequest(request);

Сначала вы должны использовать JAXB для запроса маршала в правильно экранированную строку и установите для sa значение requestDocument:

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

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

Реализация marshal(request) остается в виде упражнения.;)