XJC无法正确生成混合元素类,寻求技术解决方案
解决xjc从DTD生成混合内容类时忽略子元素的问题
问题原因
xjc(JAXB 2.3.1)处理DTD中的混合内容定义<!ELEMENT Description ( #PCDATA | ShortName )* >时,默认会将其解析为纯文本内容,只生成带@XmlValue注解的String属性,忽略了ShortName子元素的结构,导致无法生成包含文本和子元素的目标XML。
解决方案
有两种可行的处理方式:
1. 手动修改生成的Description类
直接调整生成的Description类,替换原有的value属性为支持混合内容的列表结构:
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = { "content" }) @XmlRootElement(name = "Description") public class Description { @XmlAttribute(name = "xml:lang", required = true) @XmlJavaTypeAdapter(NormalizedStringAdapter.class) protected String xmlLang; @XmlMixed @XmlElementRef(name = "ShortName", type = ShortName.class, required = false) protected List<Object> content; // 生成getter和setter方法 public String getXmlLang() { return xmlLang; } public void setXmlLang(String value) { this.xmlLang = value; } public List<Object> getContent() { if (content == null) { content = new ArrayList<Object>(); } return this.content; } }
这样content列表中可以同时存放文本字符串和ShortName对象,序列化时就能生成目标XML结构。
2. 通过绑定文件让xjc自动生成正确结构
创建绑定文件binding.xjb,指定xjc对Description元素的混合内容处理规则:
<jaxb:bindings version="2.3" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc"> <jaxb:bindings schemaLocation="your.dtd" node="/"> <jaxb:bindings node="//ELEMENT[@name='Description']"> <jaxb:property> <jaxb:baseType name="java.util.List"/> <jaxb:mixed/> </jaxb:property> </jaxb:bindings> </jaxb:bindings> </jaxb:bindings>
然后在Maven的xjc插件配置中引入该绑定文件:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>jaxb2-maven-plugin</artifactId> <version>2.5.0</version> <executions> <execution> <goals> <goal>xjc</goal> </goals> </execution> </executions> <configuration> <schemaFiles>your.dtd</schemaFiles> <bindingFiles>binding.xjb</bindingFiles> <extension>true</extension> </configuration> </plugin>
重新执行Maven构建,xjc就会自动生成包含混合内容列表的Description类,无需手动修改。
使用示例
构建目标XML时,只需向content列表中添加文本和ShortName对象即可:
Description desc = new Description(); desc.setXmlLang("pt_BR"); List<Object> content = desc.getContent(); content.add("a large ball made of leather or plastic and filled with air, used in games of soccer"); ShortName shortName = new ShortName(); shortName.setValue("Soccer ball"); content.add(shortName); // 序列化XML JAXBContext context = JAXBContext.newInstance(Description.class); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(desc, System.out);
内容的提问来源于stack exchange,提问作者Rafael Santos
相关产品推荐
相关产品推荐

