【问题标题】:XML Schema for variable element type可变元素类型的 XML 模式
【发布时间】:2013-03-03 03:08:22
【问题描述】:

我有一个用于用户界面工具的 XML 元素,如下所示:

<Layout Type="{type}"...>

如果类型是“堆栈”,则元素如下所示:

<Layout Type="Stack" Orientation="Horizontal"/>

但如果是“边距”,则元素是

<Layout Type="Margin" North="1" Center="3"/>

我正在努力编写一个应对此问题的 XML 模式。我们将不胜感激。

【问题讨论】:

    标签: xml xsd


    【解决方案1】:

    一种简单的方法是将元素 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 架构。

    【讨论】:

    • 谢谢!这至少在某种意义上是有帮助的,看起来微不足道的事情实际上有点棘手(所以我觉得不那么愚蠢)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-13
    • 1970-01-01
    • 1970-01-01
    • 2012-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多