How to generate with java a xml with CDATA on a specific field

126 views Asked by At

I would like to update an old piece of code, but I can't find the correct way to do it with the new system suggested from the deprecated class XmlSerializer, it was deprecated in Xerces 2.9.0. and it is recommended that new applications use the DOM Level 3 LSSerializer or JAXP's Transformation API for XML (TrAX) for serializing XML.

I need to generate an xml from a java class (no problem in that), but adding the prefix characters <![CDATA[ and suffix characters ]]> on the specific field outerHtml of the xml.

Here the old code with the method "generateXmlWithCDATA" i want to update:


        import java.io.File;
        import java.io.FileOutputStream;
        import java.io.IOException;
        import java.io.OutputStream;
        import java.io.Serializable;
        import java.io.StringWriter;
        import java.io.Writer;
        import java.nio.charset.StandardCharsets;
        import java.util.Date;
        import java.util.HashMap;
        import java.util.List;
        import java.util.Map;
        
        import javax.xml.bind.JAXBContext;
        import javax.xml.bind.JAXBException;
        import javax.xml.bind.Marshaller;
        
        import org.apache.commons.codec.binary.Base64;
        import org.apache.commons.io.FileUtils;
        import org.apache.commons.io.IOUtils;
        import org.apache.xml.serialize.OutputFormat;
        import org.apache.xml.serialize.XMLSerializer;

    private static File generateXmlWithCDATA(MyObjectJava myObjectJava, File fileXmlOutput) throws JAXBException, IOException {
        JAXBContext requestJaxbContext = JAXBContext.newInstance(MyObjectJava.class);
    
        Marshaller marshaller = requestJaxbContext.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
         // get an Apache XMLSerializer configured to generate CDATA
        try(OutputStream out = new FileOutputStream(fileXmlOutput)) {       
            XMLSerializer serializer = getXMLSerializer(out);       
            marshaller.marshal(myObjectJava, serializer.asContentHandler());   
        }
        return fileXmlOutput;
    }


    private static XMLSerializer getXMLSerializer(OutputStream os) {
        // 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[] { 
                    "^outerHtml"   // <outerHtml>
            });   
    
        // set any other options you'd like
        of.setPreserveSpace(true);
        of.setIndenting(true);
    
        // create the serializer
        final XMLSerializer serializer = new XMLSerializer(of);
        serializer.setOutputByteStream(os);
    
        return serializer;
    }

the xml output is something like this


        <MyObjectJava>
          <name>Leo</name>
          <surname>DaVinci</surname>
          <outerHtml><![CDATA[<a href="https://www.isasite.com">Is a site</a>]]></outerHtml>
        </MyObjectJava>

Anyone can give a example with the new system ?

Ty in advance.

2

There are 2 answers

0
4535992 On BEST ANSWER

Ty to Michael Kay suggestion, i find asolution XD

    private static File generateXmlWithCDATAV2(MyObjectJava myObjectJava, File fileXmlOutput) throws Exception {
    JAXBContext requestJaxbContext = JAXBContext.newInstance(MyObjectJava.class);
    
    Marshaller marshaller = requestJaxbContext.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    final DOMResult domResult = new DOMResult();
    marshaller.marshal(myObjectJava, domResult);
    
    Transformer transformer1 = TransformerFactory.newInstance().newTransformer();
    transformer1.setOutputProperty(OutputKeys.INDENT, "yes");
    transformer1.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
    transformer1.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS, "outerHtml");
    transformer1.transform(
            new DOMSource(domResult.getNode()), 
            new StreamResult(fileXmlOutput));
    return fileXmlOutput;
}
0
Michael Kay On

If you decide to go for the JAXP serializer, you can declare elements whose content is to be serialized as CDATA using the serialization property CDATA_SECTION_ELEMENTS, but you can't control it at the level of individual element instances.