代码之家  ›  专栏  ›  技术社区  ›  Bjørn Stenfeldt

当xs:choice中使用同一字段名两次时,如何使用jaxb从xsd文件生成java?

  •  1
  • Bjørn Stenfeldt  · 技术社区  · 6 年前

    我有一个java maven项目,需要从xsd文件集合中生成java类。我正在使用JAXB2 Maven插件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用于模式的两个不同部分,这是对的。通常我只会使用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。

    2 回复  |  直到 6 年前
        1
  •  0
  •   lexicore    6 年前

    免责声明: 我是 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简化插件 . 这是怎么回事。

    首先,添加 JAXB2简化插件 你的jaxb代码生成。见 this guide 是的。与 这看起来像:

            <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插件提供配置(比如 )中。

    下一步,您必须将要简化的属性转换为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

        2
  •  0
  •   Bjørn Stenfeldt    6 年前

    有人在这里发布了一个答案,说我应该在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:绑定,我有。多亏了那个人。那将是我接受的答案。