【问题标题】:Restricting XML attribute to enum values将 XML 属性限制为枚举值
【发布时间】:2012-08-10 03:07:06
【问题描述】:

这是我为 WS 创建的 XSD 架构

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    elementFormDefault="qualified" attributeFormDefault="unqualified">

<xs:element name="shipmentStatus" type="shipmentStatusType" />

<xs:complexType name="shipmentStatusType">
    <xs:sequence>
        <xs:element name="orderNumber" type="xs:int"/>
    </xs:sequence>

    <xs:attribute name="requestStatus">
        <xs:simpleType>
            <xs:restriction base="xs:string">
                <xs:enumeration value="SHIPPED"/>
                <xs:enumeration value="PENDING"/>
            </xs:restriction>
        </xs:simpleType>
    </xs:attribute>

</xs:complexType>

当我使用 JAXB 2.1 生成 Java 类时,它只生成了一个类,即 shippingStatusType。我期待它会生成 requestStatus 作为 JAVA 枚举,但它没有。这是预期的行为还是我错过了什么?

【问题讨论】:

    标签: java xsd jaxb schema


    【解决方案1】:

    只需将您的枚举/简单类型声明提取到顶层并将其用作 XML 属性的类型:

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema targetNamespace="http://www.example.com" xmlns="http://www.example.com"
        xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
        attributeFormDefault="unqualified">
    
        <xs:simpleType name="requestStatus">
            <xs:restriction base="xs:string">
                <xs:enumeration value="SHIPPED" />
                <xs:enumeration value="PENDING" />
            </xs:restriction>
        </xs:simpleType>
    
        <xs:complexType name="shipmentStatus">
            <xs:sequence>
                <xs:element name="orderNumber" type="xs:int" />
            </xs:sequence>
            <xs:attribute name="requestStatus" type="requestStatus" />
        </xs:complexType>
    
        <xs:element name="shipmentStatus" type="shipmentStatus" />
    
    </xs:schema>
    

    它会给你这样一个枚举:

    /**
     * <p>Java class for requestStatus.
     * 
     * <p>The following schema fragment specifies the expected content contained within this class.
     * <p>
     * <pre>
     * &lt;simpleType name="requestStatus">
     *   &lt;restriction base="{http://www.w3.org/2001/XMLSchema}string">
     *     &lt;enumeration value="SHIPPED"/>
     *     &lt;enumeration value="PENDING"/>
     *   &lt;/restriction>
     * &lt;/simpleType>
     * </pre>
     * 
     */
    @XmlType(name = "requestStatus")
    @XmlEnum
    public enum RequestStatus {
    
        SHIPPED,
        PENDING;
    
        public String value() {
            return name();
        }
    
        public static RequestStatus fromValue(String v) {
            return valueOf(v);
        }
    
    }
    

    和拥有它的班级:

    /**
     * <p>Java class for shipmentStatus complex type.
     * 
     * <p>The following schema fragment specifies the expected content contained within this class.
     * 
     * <pre>
     * &lt;complexType name="shipmentStatus">
     *   &lt;complexContent>
     *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
     *       &lt;sequence>
     *         &lt;element name="orderNumber" type="{http://www.w3.org/2001/XMLSchema}int"/>
     *       &lt;/sequence>
     *       &lt;attribute name="requestStatus" type="{http://www.example.com}requestStatus" />
     *     &lt;/restriction>
     *   &lt;/complexContent>
     * &lt;/complexType>
     * </pre>
     * 
     * 
     */
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "shipmentStatus", propOrder = {
        "orderNumber"
    })
    public class ShipmentStatus {
    
        protected int orderNumber;
        @XmlAttribute(name = "requestStatus")
        protected RequestStatus requestStatus;
    
        /**
         * Gets the value of the orderNumber property.
         * 
         */
        public int getOrderNumber() {
            return orderNumber;
        }
    
        /**
         * Sets the value of the orderNumber property.
         * 
         */
        public void setOrderNumber(int value) {
            this.orderNumber = value;
        }
    
        /**
         * Gets the value of the requestStatus property.
         * 
         * @return
         *     possible object is
         *     {@link RequestStatus }
         *     
         */
        public RequestStatus getRequestStatus() {
            return requestStatus;
        }
    
        /**
         * Sets the value of the requestStatus property.
         * 
         * @param value
         *     allowed object is
         *     {@link RequestStatus }
         *     
         */
        public void setRequestStatus(RequestStatus value) {
            this.requestStatus = value;
        }
    
    }
    

    【讨论】:

    • 您不必将类型设为全局即可使其工作。在某些情况下,XSD 不能或不应该更改。对于提供的XSD,解决方案其实是使用自定义绑定文件。
    【解决方案2】:

    我认为你在问同样的问题as this SO post。您需要创建一个自定义绑定文件来将此简单类型映射到枚举。

    绑定文件:

    <jaxb:bindings 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" version="2.1"> 
        <jaxb:globalBindings generateIsSetMethod="true" fixedAttributeAsConstantProperty="true"> 
            <xjc:serializable/> 
        </jaxb:globalBindings> 
        <jaxb:bindings schemaLocation="file:/..../restricting-xml-attribute-to-enum-values.xsd"> 
            <jaxb:bindings node="//xs:complexType[@name='shipmentStatusType']/xs:attribute[@name='requestStatus']/xs:simpleType"> 
                <jaxb:typesafeEnumClass name="MyEnumType"/> 
            </jaxb:bindings> 
        </jaxb:bindings> 
    </jaxb:bindings> 
    

    生成的类(相关部分):

    /**
     * <p>Java class for null.
     * 
     * <p>The following schema fragment specifies the expected content contained within this class.
     * <p>
     * <pre>
     * &lt;simpleType>
     *   &lt;restriction base="{http://www.w3.org/2001/XMLSchema}string">
     *     &lt;enumeration value="SHIPPED"/>
     *     &lt;enumeration value="PENDING"/>
     *   &lt;/restriction>
     * &lt;/simpleType>
     * </pre>
     * 
     */
    @XmlType(name = "")
    @XmlEnum
    public enum MyEnumType {
    
        SHIPPED,
        PENDING;
    
        public String value() {
            return name();
        }
    
        public static ShipmentStatusType.MyEnumType fromValue(String v) {
            return valueOf(v);
        }
    
    }
    

    【讨论】:

    • 不,我已经按照“SO”建议的方式工作了。但它没有用
    • @EmAe,我不敢苟同。这意味着你没有遵循这个想法。问题是您不必修改 XSD,并且您应该避免要求您这样做的解决方案,除非该工具无法真正处理它。
    猜你喜欢
    • 1970-01-01
    • 2012-02-14
    • 1970-01-01
    • 2012-03-26
    • 2020-07-19
    • 2017-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多