问题描述
在XSD文件中,需要定义:
In a XSD file, a want to define:
- 父类型(包含10个节点)。
- a 7个子类型(每个子类型包含相同的10个节点,但第二个节点的类型不同)。
可以通过限制父类型来定义子类型(父类型将成为子类型的基本类型)。问题:在子类型中,我必须再次写出父类型的所有节点(不仅是第二个节点)。问题:我可以只写覆盖的节点(第二个节点)吗?
It can be done by defining the child types by restriction on the parent type (the parent type will be the base type for the child types). The problem: In child types, I have to write again all the nodes of the parent type (not only the 2nd node). The question: Can I write only the node that I'm overriding (the 2nd node)?
示例:如果我定义了以下父级类型:
Example: If I define the following parent type:
<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>
然后我必须通过限制父母来定义孩子:
then I have to define the childs by restriction on the parent:
<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)
这是很多书面代码和重复代码(对于每个孩子,我必须再次为所有原始节点(已经在父节点上)编写)。我宁愿只写我要覆盖的节点,像这样:
That is a lot of writting and DUPLICATED code (for each child, I have to write AGAIN all the original nodes, that are already at the parent). I would prefer to write only the node that I am overriding, something like this:
<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,因此可以使用其所有高级功能。
Is there some way to avoid the duplication of code? I'm using XSD 1.1, so I can use all of its advanced features.
我知道我可以使用扩展名而不是限制:例如,我可以排除第二个父类型中的节点,并通过扩展将其添加到子类型。但是,在那种情况下,它不是第二个节点,而是第十个节点。我想在子节点上重新定义(或添加)第二个节点。
I know I can use extension instead of restriction: For example, I could exclude the 2nd node from the parent type, and add it by extension at the childs. But, in that case, it wouldn't be the 2nd node, it would be the 10th node. I want to redefine (or to add) the 2nd node at the childs.
更新:已解决:我喜欢Sperberg-McQueen提供的解决方法:模型组。模型组就像C中的宏一样,其内容得以扩展。因此,我可以为更改后的节点之前的节点定义模型组,并为更改后的节点定义其他模型组。例如:
Update: Solved: I like the workaround given by Sperberg-McQueen: Model groups. A model group is like a macro in C, its content is expanded. So I can define a model group for nodes before the changed node, and other model group for nodes after it. For example:
<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>
它比理想的解决方案(每种类型)需要多两行,但总比没有好。
It requires 2 more lines (per type) than the ideal solution, but it is better than nothing.
推荐答案
没有重复内容模型的简单方法来定义所需的关系。有一些可能的解决方法。
There is no straightforward way to define the relations you want without repeating the content model. There are some possible workarounds.
一种避免重复的方法:将通用实体用于内容模型的不变部分。 (如果您不幸使用不支持对架构文档使用DTD的XSD验证程序来解决问题,则需要使用xmllint或rxp之类的工具来扩展实体,或者在模式文档,然后再将其提供给验证程序。)
One way to avoid the duplication: use general entities for the unchanging parts of the content model. (If you have the misfortune to be stuck using an XSD validator that doesn't support the use of DTDs for schema documents, you'll need to expand the entities using a tool like xmllint or rxp, or run an XSLT identity transform on the schema document, before feeding it to the validator.)
另一种方法:将命名模型组用于内容模型的不变部分。
Another way: use named model groups for the unchanging parts of the content model.
有时第三种方法是可行的,具体取决于 type2
, type2_derived_1
, type2_derived_2
等彼此相关:使用断言强制第二个孩子成为您想要的形状。
A third way is sometimes possible, depending on how type2
, type2_derived_1
, type2_derived_2
etc. relate to each other: use assertions to force the second child into the shape you desire.
这篇关于子类型仅从父类型重新定义一个元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!