我有一个用于用户界面工具的 XML 元素,如下所示:
<Layout Type="{type}"...>
如果 Type 为“Stack”,则元素如下所示:
<Layout Type="Stack" Orientation="Horizontal"/>
但如果它是“边距”,那么元素是
<Layout Type="Margin" North="1" Center="3"/>
我正在努力编写一个应对此问题的 XML 模式。一些帮助将不胜感激。
一种简单的方法是将元素 Layout 声明为具有名为 Type(必需)、Orientation、North 和 Center(都是可选的)的属性,并指定如果 @Type = "Stack" 那么 Orientation 是有意义的,而 North 和 Center 不是,而如果@Type = 'Margin' 那么North 和Center 表示这个或那个,而Orientation 没有任何意义。
这样做的好处是您几乎可以用任何模式语言来完成它,并且它使事情变得相对简单。它的缺点是验证共现约束的责任从验证者转移到了消费软件。
使用 XSD 1.1 的第二种方法是使用条件类型分配:声明具有适当属性的两种类型,然后指定使用每种类型的条件。
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://www.example.com/nss/layout"
targetNamespace="http://www.example.com/nss/layout"
elementFormDefault="qualified">
<!--* Strictly speaking, this type is not essential,
* but it gives an overview of the kinds of layout
* we expect and allows a reviewer to have more
* confidence that the conditional type assignment
* covers all the necessary bases. *-->
<xs:simpleType name="layout-types">
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="Stack" />
<xs:enumeration value="Margin" />
</xs:restriction>
</xs:simpleType>
<!--* Two different types for the two different
* kinds of layout. *-->
<xs:complexType name="StackLayout">
<xs:attribute name="Type"
type="tns:layout-types"
use="required"/>
<xs:attribute name="Orientation"
type="xs:string"
use="required"/>
</xs:complexType>
<xs:complexType name="MarginLayout">
<xs:attribute name="Type"
type="tns:layout-types"
use="required"/>
<xs:attribute name="North"
type="xs:int"
use="required"/>
<xs:attribute name="Center"
type="xs:int"
use="required"/>
</xs:complexType>
<!--* The Layout element is bound to type tns:StackLayout
* if its Type attribute has the value 'Layout'.
* Otherwise, it's bound to tns:MarginLayout, if its
* Type attribute = 'Margin'. Otherwise, the Layout
* element instance is invalid.
* If there's a default type you can use, you don't
* have to use xs:error.
*-->
<xs:element name="Layout">
<xs:alternative test="@Type='Layout'"
type="tns:StackLayout"/>
<xs:alternative test="@Type='Margin'"
type="tns:MarginLayout"/>
<xs:alternative type="xs:error"/>
</xs:element>
</xs:schema>
如果您无权访问 XSD 1.1 验证器,则可以使用 Schematron 检查共现约束,或者您可以编写一个验证约束的 Relax NG 模式。