如何使用 JAXB 生成 CDATA 块?

2022-09-01 02:22:25

我正在使用 JAXB 将我的数据序列化为 XML。类代码很简单,如下所示。我想生成包含 CDATA 块的 XML,用于某些 Args 的值。例如,当前代码生成以下 XML:

<command>
   <args>
      <arg name="test_id">1234</arg>
      <arg name="source">&lt;html>EMAIL&lt;/html></arg>
   </args>
</command>

我想将“源”参数包装在CDATA中,使其如下所示:

<command>
   <args>
      <arg name="test_id">1234</arg>
      <arg name="source"><[![CDATA[<html>EMAIL</html>]]></arg>
   </args>
</command>

如何在以下代码中实现此目的?

@XmlRootElement(name="command")
public class Command {

        @XmlElementWrapper(name="args")
        protected List<Arg>  arg;
    }
@XmlRootElement(name="arg")
public class Arg {

        @XmlAttribute
        public String name;
        @XmlValue
        public String value;

        public Arg() {};

        static Arg make(final String name, final String value) {
            Arg a = new Arg();
            a.name=name; a.value=value;
            return a; }
    }

答案 1

注意:我是EclipseLink JAXB(MOXy)负责人,也是JAXB(JSR-222)专家组的成员。

如果您使用 MOXy 作为 JAXB 提供程序,则可以利用该扩展:@XmlCDATA

package blog.cdata;

import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.persistence.oxm.annotations.XmlCDATA;

@XmlRootElement(name="c")
public class Customer {

   private String bio;

   @XmlCDATA
   public void setBio(String bio) {
      this.bio = bio;
   }

   public String getBio() {
      return bio;
   }

}

详细信息


答案 2

使用 JAXB 的 Marshaller#marshal(ContentHandler) 封送到 ContentHandler 对象中。只需覆盖您正在使用的ContentHandler实现上的方法(例如JDOM的,Apache的等):charactersSAXHandlerXMLSerializer

public class CDataContentHandler extends (SAXHandler|XMLSerializer|Other...) {
    // see http://www.w3.org/TR/xml/#syntax
    private static final Pattern XML_CHARS = Pattern.compile("[<>&]");

    public void characters(char[] ch, int start, int length) throws SAXException {
        boolean useCData = XML_CHARS.matcher(new String(ch,start,length)).find();
        if (useCData) super.startCDATA();
        super.characters(ch, start, length);
        if (useCData) super.endCDATA();
    }
}

这比使用该方法要好得多,因为您不必对任何元素列表进行硬编码。仅当需要 CDATA 块时,它才会自动输出 CDATA 块。XMLSerializer.setCDataElements(...)