我有一个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;
}
我原本希望每个属性都能有一个吸气剂,但我却遇到了这场噩梦。
这是因为在模式的2个不同部分中使用了OBJECTDESCR,这是正确的。通常,我只会使用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。
答案 0 :(得分:0)
免责声明::我是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代码生成中。参见this guide。使用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
答案 1 :(得分:0)
有人在这里发布了答案,说我应该在我的bindings.xjb中尝试这样的事情:
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jxb:bindings>
<jxb:globalBindings choiceContentProperty="true"/>
</jxb:bindings>
</jxb:bindings>
我不知道答案在哪里,但是我尝试了它的建议并奏效了。它运行得非常好,我已经能够删除我拥有的所有其他jxb:bindings。因此,无论是谁。那将是我接受的答案。