Search code examples
javaxmlxml-serializationcdata

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


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.


Solution

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