JAXB避免使用JAXBElement <! - ? - >

时间:2014-03-19 17:32:31

标签: jaxb xsd jaxbelement

我想从XSD文件中使用JAXB生成Java类。

问题是,我总是得到一些像这样的类(删除命名空间):

public static class Action {

            @XmlElementRefs({
                @XmlElementRef(name = "ReportStateCanceled", namespace = "http://...", type = JAXBElement.class, required = false),
                @XmlElementRef(name = "ReportDate", namespace = "http://...", type = JAXBElement.class, required = false),
                @XmlElementRef(name = "ReportStatePreliminary", namespace = "http://...", type = JAXBElement.class, required = false),
                @XmlElementRef(name = "DocumentID", namespace = "http://...", type = JAXBElement.class, required = false),
                @XmlElementRef(name = "ReportStateNotValidated", namespace = "http://...", type = JAXBElement.class, required = false),
                @XmlElementRef(name = "CaseNo", namespace = "http://...", type = JAXBElement.class, required = false),
                @XmlElementRef(name = "PatientID", namespace = "http://...", type = JAXBElement.class, required = false),
                @XmlElementRef(name = "DocumentKey", namespace = "http://...", type = JAXBElement.class, required = false),
                @XmlElementRef(name = "ReportTime", namespace = "http://...", type = JAXBElement.class, required = false),
                @XmlElementRef(name = "ReportHeading", namespace = "http://...", type = JAXBElement.class, required = false),
                @XmlElementRef(name = "ReportStateComplete", namespace = "http://...", type = JAXBElement.class, required = false)
            })
            protected List<JAXBElement<?>> documentKeyOrDocumentIDOrPatientID;
            @XmlAttribute(name = "name")
            protected String name;
            @XmlAttribute(name = "Query")
            protected String query;

            /**
             * Gets the value of the documentKeyOrDocumentIDOrPatientID 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 documentKeyOrDocumentIDOrPatientID property.
             * 
             * <p>
             * For example, to add a new item, do as follows:
             * <pre>
             *    getDocumentKeyOrDocumentIDOrPatientID().add(newItem);
             * </pre>
             * 
             * 
             * <p>
             * Objects of the following type(s) are allowed in the list
             * {@link JAXBElement }{@code <}{@link Template.Page.Actions.Action.ReportDate }{@code >}
             * {@link JAXBElement }{@code <}{@link String }{@code >}
             * {@link JAXBElement }{@code <}{@link String }{@code >}
             * {@link JAXBElement }{@code <}{@link String }{@code >}
             * {@link JAXBElement }{@code <}{@link String }{@code >}
             * {@link JAXBElement }{@code <}{@link String }{@code >}
             * {@link JAXBElement }{@code <}{@link String }{@code >}
             * {@link JAXBElement }{@code <}{@link String }{@code >}
             * {@link JAXBElement }{@code <}{@link String }{@code >}
             * {@link JAXBElement }{@code <}{@link Template.Page.Actions.Action.ReportTime }{@code >}
             * {@link JAXBElement }{@code <}{@link String }{@code >}
             * 
             * 
             */
            public List<JAXBElement<?>> getDocumentKeyOrDocumentIDOrPatientID() {
                if (documentKeyOrDocumentIDOrPatientID == null) {
                    documentKeyOrDocumentIDOrPatientID = new ArrayList<JAXBElement<?>>();
                }
                return this.documentKeyOrDocumentIDOrPatientID;
            }

            /**
             * Gets the value of the name property.
             * 
             * @return
             *     possible object is
             *     {@link String }
             *     
             */
            public String getName() {
                return name;
            }

            /**
             * Sets the value of the name property.
             * 
             * @param value
             *     allowed object is
             *     {@link String }
             *     
             */
            public void setName(String value) {
                this.name = value;
            }

            /**
             * Gets the value of the query property.
             * 
             * @return
             *     possible object is
             *     {@link String }
             *     
             */
            public String getQuery() {
                return query;
            }

            /**
             * Sets the value of the query property.
             * 
             * @param value
             *     allowed object is
             *     {@link String }
             *     
             */
            public void setQuery(String value) {
                this.query = value;
            }


            /**
             * <p>Java class for anonymous complex type.
             * 
             * <p>The following schema fragment specifies the expected content contained within this class.
             * 
             * <pre>
             * &lt;complexType>
             *   &lt;simpleContent>
             *     &lt;extension base="&lt;http://www.w3.org/2001/XMLSchema>string">
             *       &lt;attribute name="dateFormat" type="{http://www.w3.org/2001/XMLSchema}string" />
             *     &lt;/extension>
             *   &lt;/simpleContent>
             * &lt;/complexType>
             * </pre>
             * 
             * 
             */
            @XmlAccessorType(XmlAccessType.FIELD)
            @XmlType(name = "", propOrder = {
                "value"
            })
            public static class ReportDate {

                @XmlValue
                protected String value;
                @XmlAttribute(name = "dateFormat")
                protected String dateFormat;

                /**
                 * Gets the value of the value property.
                 * 
                 * @return
                 *     possible object is
                 *     {@link String }
                 *     
                 */
                public String getValue() {
                    return value;
                }

                /**
                 * Sets the value of the value property.
                 * 
                 * @param value
                 *     allowed object is
                 *     {@link String }
                 *     
                 */
                public void setValue(String value) {
                    this.value = value;
                }

                /**
                 * Gets the value of the dateFormat property.
                 * 
                 * @return
                 *     possible object is
                 *     {@link String }
                 *     
                 */
                public String getDateFormat() {
                    return dateFormat;
                }

                /**
                 * Sets the value of the dateFormat property.
                 * 
                 * @param value
                 *     allowed object is
                 *     {@link String }
                 *     
                 */
                public void setDateFormat(String value) {
                    this.dateFormat = value;
                }

            }

如您所见,JAXB使用JAXBElement。这些课程对我来说无法使用。


经过一番研究后,我发现JAXB与nillable="true"minOccurs="0"一起出现问题,但我不会在任何地方使用nillable。我很确定,问题与minOccursmaxOccurs

有关

即使我知道确切的问题也会出现问题,因为我从外部人那里得到了XSD,我不允许修改它。

XSD片段:

<xs:element name="Action" minOccurs="0" maxOccurs="unbounded">
    <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
            <xs:element name="DocumentKey" type="xs:string" minOccurs="0" maxOccurs="1"/>
            <xs:element name="DocumentID" type="xs:string" minOccurs="0" maxOccurs="1"/>
            <xs:element name="PatientID" type="xs:string" minOccurs="0" maxOccurs="1"/>
            <xs:element name="CaseNo" type="xs:string" minOccurs="0" maxOccurs="1"/>
            <xs:element name="ReportHeading" type="xs:string" minOccurs="0" maxOccurs="1"/>
            <xs:element name="ReportDate" minOccurs="0" maxOccurs="1">
                <xs:complexType>
                    <xs:simpleContent>
                        <xs:extension base="xs:string" >
                            <xs:attribute name="dateFormat" type="xs:string" />
                        </xs:extension>
                    </xs:simpleContent>
                </xs:complexType>
            </xs:element>
            <xs:element name="ReportTime" minOccurs="0" maxOccurs="1">
                <xs:complexType>
                    <xs:simpleContent>
                        <xs:extension base="xs:string" >
                            <xs:attribute name="timeFormat" type="xs:string" />
                        </xs:extension>
                    </xs:simpleContent>
                </xs:complexType>
            </xs:element>
            <xs:element name="ReportStateNotValidated" type="xs:string" minOccurs="0" maxOccurs="1"/>
            <xs:element name="ReportStatePreliminary" type="xs:string" minOccurs="0" maxOccurs="1"/>
            <xs:element name="ReportStateComplete" type="xs:string" minOccurs="0" maxOccurs="1"/>
            <xs:element name="ReportStateCanceled" type="xs:string" minOccurs="0" maxOccurs="1"/>
        </xs:choice>
        <xs:attribute name="name" type="xs:string" />
        <xs:attribute name="Query" type="xs:string" />
    </xs:complexType>
</xs:element>

所以我搜索了另一个解决方案。 我总是得出结论,如果我在从XSD生成类时添加一个jaxb-binding.xml,我可以解决问题。

我尝试了一些绑定,但它从未奏效。

通过这种绑定,我获得了更少的JAXBElements,但是我获得了接口而不是类。

    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
               xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
               jaxb:extensionBindingPrefixes="xjc"
               jaxb:version="2.0">

        <xs:annotation>
            <xs:appinfo>
                <jaxb:globalBindings generateValueClass="false" generateElementProperty="false" >
                    <xjc:simple />
                </jaxb:globalBindings>
            </xs:appinfo>
        </xs:annotation>
    </xs:schema>

现在我问是否有人知道解决方案? 最好的解决方案是,如果有人为我提供了一个有效的jaxb-binding.xml。

我使用的是xjc编译器的2.2.4-2版本。

提前谢谢!

2 个答案:

答案 0 :(得分:5)

我完全为这个问题写了Simpify plugin

<xs:schema ...
    xmlns:simplify="http://jaxb2-commons.dev.java.net/basic/simplify"
    jaxb:extensionBindingPrefixes="... simplify">

<xs:complexType name="typeWithReferencesProperty">
    <xs:choice maxOccurs="unbounded">
        <xs:element name="a" type="someType">
            <xs:annotation>
                <xs:appinfo>
                    <simplify:as-element-property/>
                </xs:appinfo>
            </xs:annotation>
        </xs:element>
        <xs:element name="b" type="someType"/>
    </xs:choice> 
</xs:complexType>

会给你

@XmlElement(name = "a")
protected List<SomeType> a;
@XmlElement(name = "b")
protected List<SomeType> b;

而不是

@XmlElementRefs({
    @XmlElementRef(name = "a", type = JAXBElement.class),
    @XmlElementRef(name = "b", type = JAXBElement.class)
})
protected List<JAXBElement<SomeType>> aOrB;

免责声明:我是作者。

答案 1 :(得分:3)

问题

问题是您的xs:choice元素有maxOccurs="unbounded"

<xs:choice minOccurs="0" maxOccurs="unbounded">

JAXB规范参考

因为这个JAXB无法为选择结构中的每个选项生成单独的属性。有关更多详细信息,请参阅JAXB 2.2(JSR-222)规范的“6.12.6绑定重复发生模型组”:

为什么会出现问题

以下XML片段根据您的XML架构有效,并且需要能够在生成的对象模型中表示。

<Action>
    <DocumentID/>
    <PatientID/>
    <PatientID/>
    <DocumentID/>
</Action>

解决方法

如果您真的不喜欢JAXB生成的类,您可以创建自己的类,并通过绑定文件指定JAXB应该使用它而不是创建新的。

<jxb:bindings schemaLocation="yourSchema.xsd">
    <jxb:bindings node="//xs:element[@name='Action']">
        <jxb:class ref="com.example.Action"/>
    </jxb:bindings>
</jxb:bindings>