覆盖和更改基类型中的Xml元素

时间:2013-01-18 03:35:15

标签: xml xsd schema override

我有一个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>

现在假设我要定义一个 Honda 汽车类型,该类型从 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 中定义的值。

我可以在扩展类型中覆盖掩盖基本 Fuel 元素吗?

2 个答案:

答案 0 :(得分:7)

您可以执行与您描述的内容非常相似的操作,但在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的东西,并且一次产生你想到的本田变体

我希望这会有所帮助。

答案 1 :(得分:-1)

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

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

为所有属性创建通常的getter / setter,除了你想为可扩展性做通用的属性:

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

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

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

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

我希望这会有所帮助。