java - 当在 xs:choice 中使用两次相同的字段名称时,如何使用 JAXB 从 XSD 文件生成 java?
问题描述
我有一个 Java maven 项目,需要从一组 XSD 文件中生成 Java 类。我正在使用 jaxb2-maven-plugin 2.4。XSD 文件之一包含以下代码段:
<xs:choice>
<xs:sequence>
<xs:element name="LOT_DIVISION" type="lot_division_f01"/>
<xs:element name="OBJECT_DESCR" type="object_f01"/>
</xs:sequence>
<xs:sequence>
<xs:element ref="NO_LOT_DIVISION"/>
<xs:element name="OBJECT_DESCR" type="object_f01"/>
</xs:sequence>
</xs:choice>
当我尝试为此使用 JAXB 自动生成 Java 类时,我最终得到如下结果:
/**
* Gets the rest of the content model.
*
* <p>
* You are getting this "catch-all" property because of the following reason:
* The field name "OBJECTDESCR" is used by two different parts of a schema. See:
* line 142 of file:/C:/Projects/main/web/service/src/xsd/ted/209/F01_2014.xsd
* line 138 of file:/C:/Projects/main/web/service/src/xsd/ted/209/F01_2014.xsd
* <p>
* To get rid of this property, apply a property customization to one
* of both of the following declarations to change their names:
* Gets the value of the content property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the content property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getContent().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link JAXBElement }{@code <}{@link TextFtSingleLine }{@code >}
* {@link JAXBElement }{@code <}{@link String }{@code >}
* {@link JAXBElement }{@code <}{@link CpvSet }{@code >}
* {@link JAXBElement }{@code <}{@link TypeContract }{@code >}
* {@link JAXBElement }{@code <}{@link TextFtMultiLines }{@code >}
* {@link JAXBElement }{@code <}{@link Val }{@code >}
* {@link JAXBElement }{@code <}{@link LotDivisionF01 }{@code >}
* {@link JAXBElement }{@code <}{@link ObjectF01 }{@code >}
* {@link JAXBElement }{@code <}{@link Empty }{@code >}
* {@link JAXBElement }{@code <}{@link XMLGregorianCalendar }{@code >}
*
*
*/
public List<JAXBElement<?>> getContent() {
if (content == null) {
content = new ArrayList<JAXBElement<?>>();
}
return this.content;
}
我期待每个属性都有一个吸气剂,但我却得到了这个包罗万象的噩梦。
它说这是因为 OBJECTDESCR 用于模式的 2 个不同部分,这是正确的。通常我只会使用 bindings.xjb 重命名一个或另一个,但我不知道在这种情况下如何。
XML 数据和 XSD 文件来自http://ftp.ted.europa.eu/TED/main/HomePage.do所以我对这些部分几乎没有控制权。但我需要阅读他们的数据。
XSD 文件的完整集合可在此处获得:http : //publications.europa.eu/mdr/resource/eprocurement/ted/R2.0.9/publication/latest/ 片段来自 F01_2014.xsd。
解决方案
免责声明:我是可以完成这项工作的JAXB2 Simplify Plugin的作者。
让我们从 MCVE 开始:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="choice" type="choiceType"/>
<xs:complexType name="choiceType">
<xs:choice>
<xs:sequence>
<xs:element name="x" type="xs:string"/>
<xs:element name="z" type="xs:string"/>
</xs:sequence>
<xs:sequence>
<xs:element name="y" type="xs:string"/>
<xs:element name="z" type="xs:string"/>
</xs:sequence>
</xs:choice>
</xs:complexType>
</xs:schema>
这会产生如下代码:
@XmlElementRefs({
@XmlElementRef(name = "x", type = JAXBElement.class, required = false),
@XmlElementRef(name = "z", type = JAXBElement.class, required = false),
@XmlElementRef(name = "y", type = JAXBElement.class, required = false)
})
protected List<JAXBElement<String>> xAndZOrY;
虽然从建模的角度来看,这段代码可能更好,但它看起来很奇怪,大多数开发人员更喜欢更简单的代码。像三个独立的属性x
,y
和z
。
为此,您可以使用JAXB2 Simplify Plugin。就是这样。
首先,将JAXB2 Simplify Plugin添加到您的 JAXB 代码生成中。请参阅本指南。使用maven-jaxb2-plugin这将如下所示:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.14.0</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<args>
<arg>-Xsimplify</arg>
</args>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics</artifactId>
<version>0.12.0</version>
</plugin>
</plugins>
</configuration>
</plugin>
抱歉,我不会在这里提供其他 JAXB2 Maven 插件的配置(如jaxb2-maven-plugin)。
接下来,您必须为 Simplify 插件指定要简化的属性。这可以直接在模式中完成,也可以(首选方式)通过外部绑定文件完成:
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:simplify="http://jaxb2-commons.dev.java.net/basic/simplify"
jaxb:extensionBindingPrefixes="simplify"
jaxb:version="2.3">
<jaxb:bindings schemaLocation="schema.xsd" node="/xsd:schema">
<jaxb:bindings node="xsd:complexType[@name='choiceType']">
<simplify:property name="xAndZOrY">
<simplify:as-element-property/>
</simplify:property>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
这将产生以下代码:
protected List<String> x;
protected List<String> z;
protected List<String> y;
public List<String> getX() { ... }
public List<String> getZ() { ... }
public List<String> getY() { ... }
您可以在此处找到完整的工作示例:
https://github.com/highsource/jaxb2-basics-support/tree/master/s/simplify-choice
推荐阅读
- python - 烧瓶重定向后,我的数据无效
- javascript - Angular 中的后台数据加载和解析器
- javascript - CSS - 改变盒子大小和链接背景图片
- java - 我可以在java中实现一个带有变量的类吗?
- oracle11g - 如何删除 - 从右到左读取字符串值时
- swift - 为什么 URLSession 不在 URLSessionDownloadDelegate 中?
- django - 如何将查询参数传递给 django rest api javascript 客户端
- c# - 从日期时间中减去未知间隔
- java - 迭代数组并打印不同的字符串输出
- angular - Ionic 4:创建模拟存储