代码之家  ›  专栏  ›  技术社区  ›  Fiona - myaccessible.website

创建“灵活”的XML架构

  •  4
  • Fiona - myaccessible.website  · 技术社区  · 15 年前

    我需要为一个非常灵活的XML文件创建一个模式。必须满足以下要求:

    1. 验证我们需要存在的一些元素,并了解
    2. 验证一些可选元素,我们知道
    3. 允许任何其他元素
    4. 允许他们按任何顺序

    快速实例:

    XML

    <person>
        <age></age>
        <lastname></lastname>
        <height></height>
    </person>
    

    我的XSD尝试:

    <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name="person">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="firstname" minOccurs="0" type="xs:string"/>
            <xs:element name="lastname" type="xs:string"/>
            <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded" />
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:schema>
    

    现在,我的XSD满足了需求1和3。但是,如果firstname和lastname都是可选的,那么它不是有效的模式,因此它不满足要求2,并且顺序是固定的,这不符合要求4。

    现在,我只需要一些东西来验证我的XML。我愿意接受任何方式的建议,无论是在.NET 3.5中,还是在其他类型的模式中,都可以通过编程的方式来实现。

    有人能想出一个解决方案来满足所有4个要求吗?

    2 回复  |  直到 11 年前
        1
  •  1
  •   Luke Puplett    11 年前

    我今天一直在想这个问题。我在考虑这有多难 xs:all 规则使XML数据库能够存储类似于CMS的非结构化数据的文档,同时还可以验证数据。

    然后我突然想到,XHTML允许非常灵活地安排嵌套元素,无论您需要用什么顺序来标记页面。

    下面是XHTML 1.1模式的摘录:

      <xs:group name="InlForm.class">
        <xs:choice>
          <xs:element ref="input"/>
          <xs:element ref="select"/>
          <xs:element ref="textarea"/>
          <xs:element ref="label"/>
          <xs:element ref="button"/>
        </xs:choice>
      </xs:group>
    
      <xs:group name="Inline.extra">
        <xs:choice/>
      </xs:group>
    
      <xs:group name="Ruby.class">
        <xs:sequence>
          <xs:element ref="ruby"/>
        </xs:sequence>
      </xs:group>
    
      <!--
       Inline.class includes all inline elements,
       used as a component in mixes
      -->
      <xs:group name="Inline.class">
        <xs:choice>
          <xs:group ref="InlStruct.class"/>
          <xs:group ref="InlPhras.class"/>
          <xs:group ref="InlPres.class"/>
          <xs:group ref="I18n.class"/>
          <xs:group ref="Anchor.class"/>
          <xs:group ref="InlSpecial.class"/>
          <xs:group ref="InlForm.class"/>
          <xs:group ref="Ruby.class"/>
          <xs:group ref="Inline.extra"/>
        </xs:choice>
      </xs:group>
    
      <xs:group name="Heading.class">
        <xs:choice>
          <xs:element ref="h1"/>
          <xs:element ref="h2"/>
          <xs:element ref="h3"/>
          <xs:element ref="h4"/>
          <xs:element ref="h5"/>
          <xs:element ref="h6"/>
        </xs:choice>
      </xs:group>
    

    它们本质上是递归地嵌套组的选择。我想象写这篇文章的人在一个安全的机构里度过了余生,每天接受几次强制用药。

    我希望这有帮助。我认为这说明了超灵活模式是如何在XSD 1.0中“真正”完成的。

    编辑 -工作!您可以将所有其他组组成一个“主”组,并使用此示例 ListItem 元素定义允许以任意顺序连续嵌套元素。确保 李斯特 也包含在一个组中,因此递归可以工作。

      <xs:element name="ListItem">
        <xs:complexType>
          <xs:sequence>
            <xs:group ref="content:any.mix"  minOccurs="1" maxOccurs="unbounded"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    

    所以我的 any.mix 组如下:

      <xs:group name="any.mix">
        <xs:choice>      
          <xs:group ref="content:item.class" />
          <xs:group ref="content:media.class" />
          <xs:group ref="content:data.class" />
          <xs:group ref="content:list.class" />      
        </xs:choice>
      </xs:group>
    

    这些“类”组中的每一个都包含更多的组选择,等等,直到它们最终击中元素,叶级的实际标签,如果你喜欢的话。

    组本身不应具有循环引用;“trick”位于 任意混合 组,即它是一个具有无限根选项的选择树。

    卢克

        2
  •  6
  •   xcut    15 年前

    如果name元素是可选的,则无法满足您的需求3,因为您的模式随后会违反唯一的粒子属性规则(基本上,处理器不知道是针对firstname还是针对任何firstname验证firstname)。

    就验证而言,您不局限于单个模式。如果您可以在不同的名称空间中使用两个模式,那么可以这样做:

    模式一 -允许任何操作:

    <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name="document">
        <xs:complexType>
          <xs:sequence>
            <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded" />
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:schema>
    

    模式二 -为某些元素添加特定验证:

    <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://other" xmlns="http://other">
        <xs:element name="firstname" type="xs:string"/>
        <xs:element name="lastname" type="xs:string"/>
    </xs:schema>
    

    然后确保实例文档的xsi:include引用了这两个模式。