子类型仅从父类型重新定义一个元素

时间:2014-06-04 13:14:51

标签: types xsd override children

在XSD文件中,想要定义:

  • 父类型(包含10个节点)。
  • 7个子类型(每个子类型包含相同的10个节点,但第2个节点的类型不同)。

可以通过限制父类型来定义子类型(父类型将是子类型的基类型)来完成。问题:在子类型中,我必须再次写入父类型的所有节点(不仅是第二个节点)。问题:我是否只能编写我要覆盖的节点(第二个节点)?

示例:如果我定义以下父类型:

<xs:complexType name="Parent">
    <xs:sequence>
        <xs:element name="Node1" type="type1" />
        <xs:element name="Node2" type="type2" />
        <xs:element name="Node3" type="type3" />
        ...
        <xs:element name="Node10" type="type10" />
    </xs:sequence>
</xs:complexType>

然后我必须通过对父母的限制来定义孩子:

<xs:complexType name="Child1">
    <xs:complexContent>
        <xs:restriction base="Parent">
            <xs:sequence>
                <xs:element name="Node1" type="type1" />
                <xs:element name="Node2" type="type2_derived_1" />
                <xs:element name="Node3" type="type3" />
                ...
                <xs:element name="Node10" type="type10" />
            </xs:sequence>
        </xs:restriction>
    </xs:complexContent>
</xs:complexType> 

<xs:complexType name="Child2">
    <xs:complexContent>
        <xs:restriction base="Parent">
            <xs:sequence>
                <xs:element name="Node1" type="type1" />
                <xs:element name="Node2" type="type2_derived_2" />
                <xs:element name="Node3" type="type3" />
                ...
                <xs:element name="Node10" type="type10" />
            </xs:sequence>
        </xs:restriction>
    </xs:complexContent>
</xs:complexType> 

...
(same for all the 10 childs)

这是很多写和DUPLICATED代码(对于每个孩子,我必须写AGAIN所有原始节点,已经在父节点)。我更愿意只编写我要覆盖的节点,如下所示:

<xs:complexType name="Child1">
    <xs:complexContent>
        <xs:restriction base="Parent">
            <xs:changed>
                <xs:element name="Node2" type="type2_derived_1" />
            </xs:changed>
        </xs:restriction>
    </xs:complexContent>
</xs:complexType> 

<xs:complexType name="Child2">
    <xs:complexContent>
        <xs:restriction base="Parent">
            <xs:changed>
                <xs:element name="Node2" type="type2_derived_2" />
            </xs:changed>
        </xs:restriction>
    </xs:complexContent>
</xs:complexType> 

...
(same for all the 10 childs)

有没有办法避免重复代码?我正在使用XSD 1.1,所以我可以使用它的所有高级功能。

我知道我可以使用扩展而不是限制:例如,我可以从父类型中排除第二个节点,并在子节点上通过扩展名添加它。但是,在这种情况下,它不会是第二个节点,它将是第10个节点。我想重新定义(或添加)孩子们的第二个节点。


更新:已解决:我喜欢Sperberg-McQueen给出的解决方法:模型组。模型组就像C中的宏,其内容被扩展。因此,我可以在更改的节点之前为节点定义模型组,为其后的节点定义其他模型组。例如:

<xs:group name="g_node_1">
    <xs:sequence>
        <xs:element name="Node1" type="type1"/>
    </xs:sequence>
</xs:group>

<xs:group name="g_nodes_3to10">
    <xs:sequence>
        <xs:element name="Node3" type="type3"/>
        <xs:element name="Node4" type="type4"/>
        <xs:element name="Node5" type="type5"/>
        <xs:element name="Node6" type="type6"/>
        <xs:element name="Node7" type="type7"/>
        <xs:element name="Node8" type="type8"/>
        <xs:element name="Node9" type="type9"/>
        <xs:element name="Node10" type="type10"/>
    </xs:sequence>
</xs:group>

<xs:complexType name="Parent">
    <xs:sequence>
        <xs:group ref="g_node_1"/>
        <xs:element name="Node2" type="type2"/>
        <xs:group ref="g_nodes_3to10"/>
    </xs:sequence>
</xs:complexType>

<xs:complexType name="Child1">
    <xs:complexContent>
        <xs:restriction base="Parent">
            <xs:sequence>
                <xs:group ref="g_node_1"/>
                <xs:element name="Node2" type="type2_derived_1" />
                <xs:group ref="g_nodes_3to10"/>
            </xs:sequence>
        </xs:restriction>
    </xs:complexContent>
</xs:complexType> 

<xs:complexType name="Child2">
    <xs:complexContent>
        <xs:restriction base="Parent">
            <xs:sequence>
                <xs:group ref="g_node_1"/>
                <xs:element name="Node2" type="type2_derived_2" />
                <xs:group ref="g_nodes_3to10"/>
            </xs:sequence>
        </xs:restriction>
    </xs:complexContent>
</xs:complexType> 

它需要比理想解决方案多2行(每种类型),但它总比没有好。

1 个答案:

答案 0 :(得分:1)

没有重复内容模型,没有直接的方法来定义您想要的关系。有一些可能的解决方法。

避免重复的一种方法:将一般实体用于内容模型的不变部分。 (如果您不幸使用不支持将DTD用于架构文档的XSD验证器,您需要使用xmllint或rxp等工具扩展实体,或者运行XSLT在将模式文档提供给验证器之前,对模式文档进行身份转换。)

另一种方法:将命名模型组用于内容模型的不变部分。

有时可能采用第三种方式,具体取决于type2type2_derived_1type2_derived_2等相互关联的方式:使用断言强制第二个孩子进入您想要的形状。