如何使用JAXB生成CDATA块?
我正在使用 JAXB 将数据序列化为 XML。类代码很简单,如下所示。我想生成包含某些 Args 值的 CDATA 块的 XML。例如,当前代码生成此 XML:
<command>
<args>
<arg name="test_id">1234</arg>
<arg name="source"><html>EMAIL</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; }
}
I am using JAXB to serialize my data to XML. The class code is simple as given below. I want to produce XML that contains CDATA blocks for the value of some Args. For example, current code produces this XML:
<command>
<args>
<arg name="test_id">1234</arg>
<arg name="source"><html>EMAIL</html></arg>
</args>
</command>
I want to wrap the "source" arg in CDATA such that it looks like below:
<command>
<args>
<arg name="test_id">1234</arg>
<arg name="source"><[![CDATA[<html>EMAIL</html>]]></arg>
</args>
</command>
How can I achieve this in the below code?
@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; }
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
注意:我是EclipseLink JAXB (MOXy) 的领导者和 JAXB (JSR-222 )专家组。
如果您使用 MOXy 作为 JAXB 提供程序,那么您可以利用
@XmlCDATA
扩展:了解更多信息
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
If you are using MOXy as your JAXB provider then you can leverage the
@XmlCDATA
extension:For More Information
使用 JAXB 的
Marshaller#marshal(ContentHandler)
编组到ContentHandler
对象。只需重写您正在使用的 ContentHandler 实现上的characters
方法(例如 JDOM 的SAXHandler
、Apache 的XMLSerializer
等):这很多比使用
XMLSerializer.setCDataElements(...)
方法更好,因为您不必对任何元素列表进行硬编码。它仅在需要时自动输出 CDATA 块。Use JAXB's
Marshaller#marshal(ContentHandler)
to marshal into aContentHandler
object. Simply override thecharacters
method on the ContentHandler implementation you are using (e.g. JDOM'sSAXHandler
, Apache'sXMLSerializer
, etc):This is much better than using the
XMLSerializer.setCDataElements(...)
method because you don't have to hardcode any list of elements. It automatically outputs CDATA blocks only when one is required.解决方案回顾:
我通过使用 XMLStreamWriter 实现修改了 a2ndrade 的解决方案。这个解决方案效果很好。
这就是 CDataXMLStreamWriter 实现。委托类只是将所有方法调用委托给给定的 XMLStreamWriter 实现。
Solution Review:
I modified the solution of a2ndrade by using a XMLStreamWriter implementation. This solution works very well.
Thats the CDataXMLStreamWriter implementation. The delegate class simply delegates all method calls to the given XMLStreamWriter implementation.
以下是上述网站引用的代码示例:
Here is the code sample referenced by the site mentioned above:
出于与迈克尔·恩斯特相同的原因,我对这里的大多数答案都不满意。我无法使用他的解决方案,因为我的要求是将 CDATA 标签放入一组定义的字段中 - 正如 raigstorfer 的 OutputFormat 解决方案中那样。
我的解决方案是编组到 DOM 文档,然后执行 null XSL 转换来执行输出。转换器允许您设置哪些元素包含在 CDATA 标记中。
更多信息请参见:http://javacoalface.blogspot.co.uk/ 2012/09/outputting-cdata-sections-with-jaxb.html
For the same reasons as Michael Ernst I wasn't that happy with most of the answers here. I could not use his solution as my requirement was to put CDATA tags in a defined set of fields - as in raiglstorfer's OutputFormat solution.
My solution is to marshal to a DOM document, and then do a null XSL transform to do the output. Transformers allow you to set which elements are wrapped in CDATA tags.
Further info here: http://javacoalface.blogspot.co.uk/2012/09/outputting-cdata-sections-with-jaxb.html
以下简单方法在本身不支持 CDATA 的 JAX-B 中添加了 CDATA 支持:
等等,任何 CDataString 元素将在马歇尔时间封装。在解组时,将自动删除。
The following simple method adds CDATA support in JAX-B which does not support CDATA natively :
Et voila, any CDataString element will be encapsulated with at Marshall time. At unmarshall time, the will automatically be removed.
@a2ndrade
答案的补充。我在 JDK 8 中找到了一个要扩展的类。但注意到该类位于 com.sun 包中。您可以复制一份代码,以防此类在将来的 JDK 中被删除。
使用方法:
结果示例:
Supplement of
@a2ndrade
's answer.I find one class to extend in JDK 8. But noted that the class is in
com.sun
package. You can make one copy of the code in case this class may be removed in future JDK.How to use:
Result example:
从 Xerxes-J 2.9 开始,XMLSerializer 已被弃用。建议将其替换为 DOM Level 3 LSSerializer 或 JAXP 的 XML 转换 API。有人尝试过方法吗?
As of Xerxes-J 2.9, XMLSerializer has been deprecated. The suggestion is to replace it with DOM Level 3 LSSerializer or JAXP's Transformation API for XML. Has anyone tried approach?
只是警告一句:根据 javax.xml.transform.Transformer.setOutputProperty(...) 的文档,当指示来自另一个名称空间的元素时,您应该使用限定名称的语法。根据 JavaDoc (Java 1.6 rt.jar):
这不起作用 - Java 1.6 rt.jar 中的实现类,意味着 com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl 解释属于不同名称空间的元素只有当它们被声明为“http://xyz.foo.com/yada 时才正确/baz.html:foo",因为在实现中有人正在解析它以查找最后一个冒号。因此,不要调用:,
它应该根据 JavaDoc 工作,但最终会被解析为“http”和“/ /xyz.foo.com/yada/baz.html”,您必须
至少在 Java 1.6 中调用。
Just a word of warning: according to documentation of the javax.xml.transform.Transformer.setOutputProperty(...) you should use the syntax of qualified names, when indicating an element from another namespace. According to JavaDoc (Java 1.6 rt.jar):
Well this doesn't work - the implementing class from Java 1.6 rt.jar, meaning com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl interprets elements belonging to a different namespace only then correctly, when they are declared as "http://xyz.foo.com/yada/baz.html:foo", because in the implementation someone is parsing it looking for the last colon. So instead of invoking:
which should work according to JavaDoc, but ends up being parsed as "http" and "//xyz.foo.com/yada/baz.html", you must invoke
At least in Java 1.6.
以下代码将阻止对 CDATA 元素进行编码:
它还将保留
UTF-8
作为您的编码。The following code will prevent from encoding CDATA elements:
It will also keep
UTF-8
as your encoding.