6

我有一个定义汽车基本字段的 xml 模式:

<xs:simpleType name="FuelType">
    <xs:restriction base="xs:string">
        <xs:enumeration value="Regular Unleaded"/>
        <xs:enumeration value="High Octane"/>
        <xs:enumeration value="Leaded"/>
    </xs:restriction>
</xs:simpleType>
<xs:complexType name="CarType">
    <xs:sequence>
        <xs:element name="Make" type="xs:string"/>
        <xs:element name="Model" type="xs:string"/>
        <xs:element name="Cylinders" type="xs:int"/>
        <xs:element name="Fuel" type="FuelType"/>
    </xs:sequence>
</xs:complexType>

现在假设我想定义一个继承自CarType但有自己的Fuel定义的本田汽车类型:

<xs:simpleType name="HondaFuelType">
    <xs:restriction base="xs:string">
        <xs:enumeration value="85"/>
        <xs:enumeration value="87"/>
        <xs:enumeration value="89"/>
        <xs:enumeration value="91"/>
        <xs:enumeration value="93"/>
        <xs:enumeration value="95"/>
    </xs:restriction>
</xs:simpleType>
<xs:complexType name="HondaCarType">
    <xs:complexContent>
        <xs:extension base="car:CarType">
            <xs:sequence>
                <xs:element name="Fuel" type="HondaFuelType"/>
            </xs:sequence>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

扩展CarType得到了我想要的一切,但是架构现在允许两个名为Fuel的元素(在不同的命名空间中)。这是一个示例 Xml 实例:

<HondaCar xmlns="HondaNS" xmlns:car="CarNS" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="HondaNS D:\Development\Temp\honda.xsd">
    <car:Make/>
    <car:Model/>
    <car:Cylinders>4</car:Cylinders>
    <car:Fuel>High Octane</car:Fuel>
    <Fuel>87</Fuel>
</HondaCar>

尽管这是完全有效的 Xml,但它没有逻辑意义(至少对我而言)。我的意图是扩展基本类型,然后覆盖*Fuel* 以仅允许HondaFuelType中定义的值。

有没有办法可以覆盖屏蔽扩展类型中的基本燃料元素?

4

2 回答 2

8

您可以做与您描述的非常相似的事情,但在 XSD 中不可能完全按照您的描述做。复杂类型 CarType 的“基本”声明对数据消费者做出了许多承诺,所有从它派生的类型都必须遵守这些承诺,无论是通过限制还是扩展。其中包括:

  • CarType 的实例将具有名为 Make、Model、Cylinders 和 Fuel 的子代,并带有指定的类型。
  • Make 和 Model 元素的值将是字符串。
  • Cylinders 元素的值将是 xs:int。
  • Fuel 元素的值将从字符串集合 {"Regular Unleaded", "Leaded", "High Octane"} 中提取。

这是您遇到麻烦的这些承诺中的最后一个。

当您扩展一个类型时,您会在其内容模型的末尾添加新的子项;对于 XSD 1.0,对于任何对扩展有效的元素,总是可以从末尾删除零个或多个子元素并生成一个对基本类型有效的元素。这就是为什么您的扩展最终会使用两个 Fuel 元素。

如果您只想要一个 Fuel 元素,那么您要做的是限制而不是扩展 CarType。但是您想到的限制并不是对基本类型的 Fuel 元素的法律限制。所以这里的限制对你也不起作用。

当然,一种可能性是对 CarType 进行泛化,使其 Fuel 元素接受 xs:string,然后对其进行两次限制,一次生成类似于现有 CarType 的内容,一次生成您心目中的 Honda 变体。

我希望这有帮助。

于 2013-01-18T03:54:14.850 回答
-1

我有一个类似的问题,这就是我修复的方法:

在java中定义了一个抽象基类:CarType。

为所有属性创建通常的 getter/setter,除了您希望为可扩展性而通用的属性:

public <T extends CarType> T getCarType() {
    return (T) ref;
}

使用 xsd:annotation 创建具有 java 类型的 xsd 元素,以便 xsj 编译器使用正确的评估。

<xsd:complexType name="carType">
    <xsd:annotation>
        <xsd:appinfo>
            <jaxb:class ref="com.yourclass.model.CarType"/>
        </xsd:appinfo>
    </xsd:annotation>
</xsd:complexType>

现在将它用作所有其他 xsd 元素的扩展基础,就像您之前所做的那样。这将确保您可以设置/获取 CarType 的任何超类型。

我希望这有帮助。

于 2013-02-12T21:00:14.087 回答