在XSD架构中,您cannot declare an element as the only valid root node为您的文档 这是一个PITA,但我知道它。
多年来,我只会做链接答案中建议的内容 - 只定义<simpleType>
和<complexType>
s,在全局级别定义的唯一<element>
是我想要的根节点。
但是,我目前正在对我的XSD / XSLT代码库进行很好的重构。我想要做的一件事是将某个元素限制为仅从所需类型派生的元素,前提是这些派生词可以有不同的节点名称:
<xs:complexType name="parentType">
<xs:sequence>
<xs:element ref="AChild" minOccurs="1" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
其中AChild
是一个抽象基类型,其他类型将使用substitutionGroup
从中派生:
<xs:complexType name="child_base" abstract="true">
...
</xs:complexType>
<xs:element name="AChild" type="child_base" abstract="true" />
<xs:element name="AConcreteChild" substitutionGroup="AChild" >
<xs:complexType>
<xs:complexContent>
<xs:extension base="child_base">
...
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element name="AnotherPossibleConcreteChild" substitutionGroup="AChild" >
<xs:complexType>
<xs:complexContent>
<xs:extension base="child_base">
...
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
这里的问题是substitutionGroup
只适用于在全局级别声明的元素。所以现在我有一堆先前的内部type
被声明为全局级element
,虽然这完全限制了parentType
的可能子项,但这也意味着验证将成功(如果有的话)现在全局的孩子被提供作为根元素,我不想要。
我考虑的选项包括:
substitutionGroup
继承,将所有可能的子项移动到单独的命名空间,并使用<xsd:any namespace="that namespace" />
。感觉有点好,但我不喜欢额外的命名空间和更糟糕的约束。引入一个原则,根据该原则总会有两个“主”XSD架构。一个将以通常的方式验证节点(我目前的验证),另一个将只包含最松散形式的顶级节点的定义:
<xs:complexType name="parentType">
<xs:sequence>
<xs:any namespace="##any" processContents="skip" />
</xs:sequence>
<xs:anyAttribute namespace="##any" processContents="skip" />
</xs:complexType>
<xs:element name="TheRootNode" type="parentType" />
当且仅当两个模式都有效时,我的文档才是正确的 我不喜欢的是,我不确定违反最佳做法有多深。
退出重构并保留之前的内容(在我将所有可能的孩子手动列在<xs:choice>
中之前)。
我的问题是,有没有其他方法可以使any-derived-element约束工作而不声明多个全局级<element>
(以便唯一的根节点约束再次起作用)?如果您认为我最好选择一个列出的选项,请留下答案。
答案 0 :(得分:0)
使用顶级组。
它就像你的最后一个要点,但每次需要时你可以用<xs:group ref=..."/>
引用它,而不是重复选择(或者你的意思)。
<xs:complexType name="parentType">
<xs:group ref="AChild" minOccurs="1" maxOccurs="unbounded" />
</xs:complexType>
<xs:group name="AChild">
<xs:choice>
<xs:element name="AConcreteChild" type="AConcreteChild_type" />
<xs:element name="AnotherPossibleConcreteChild" type="AnotherPossibleConcreteChild_type" />
</xs:choice>
</xs:group>
BTW:我也觉得这个更清楚,因为选择在xsd中组合在一起,所以你不必扫描具有相同替换组的元素声明。