如何使用 java 在特定字段上生成带有 CDATA 的 xml

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

提问人:4535992 提问时间:7/27/2023 更新时间:7/31/2023 访问量:46

问:

我想更新一段旧代码,但我找不到正确的方法来使用已弃用的类 XmlSerializer 建议的新系统来更新,它在 Xerces 2.9.0 中已弃用。建议新应用程序使用 DOM Level 3 LSSerializer 或 JAXP 的 Transformation API for XML (TrAX) 来序列化 XML。

我需要从 java 类生成一个 xml(没有问题),但在 xml 的特定字段上添加前缀字符和后缀字符。<![CDATA[]]>outerHtml

这里是我想更新的带有方法“generateXmlWithCDATA”的旧代码:


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

XML 输出如下所示


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

任何人都可以举个新系统的例子吗?

提前 Ty。

Java XML XML 序列化 CDATA

评论

0赞 g00se 7/27/2023
怎么样?java.beans.XMLEncoder
0赞 g00se 7/27/2023
fwiw,我只是将此页面的整个 html 源代码作为 bean 属性进行循环,没有任何问题。几行代码,没有第三方库 - 只有 JRE

答:

1赞 Michael Kay 7/27/2023 #1

如果决定使用 JAXP 序列化程序,则可以使用 serialization 属性将其内容序列化为 CDATA 的元素,但不能在单个元素实例级别控制它。CDATA_SECTION_ELEMENTS

0赞 4535992 7/31/2023 #2

Ty 对 Michael Kay 的建议,我找到了一个解决方案 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;
}