创建“灵活的”XML架构

时间:2010-04-07 12:03:24

标签: xml xsd schema

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

  1. 验证我们需要出现的一些元素,并了解
  2. 的确切结构
  3. 验证一些可选的元素,并且我们知道
  4. 的确切结构
  5. 允许任何其他元素
  6. 以任何顺序允许它们
  7. 快速举例:

    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 个答案:

答案 0 :(得分:6)

如果名称元素是可选的,则无法解决您的需求号3,因为您的架构会违反唯一的粒子归因规则(基本上,处理器不会知道是否针对firstname或任何针对any来验证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>

Schema two - 为某些元素添加特定验证:

<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引用两个模式。

答案 1 :(得分:1)

我今天经常考虑这个问题。我正在考虑这个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中“真正”完成super-flexi模式。

修改 - 它有效!您可以创建所有其他组的“主”组,并使用此示例ListItem元素定义以允许以任何顺序连续嵌套元素。确保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>

每个“类”组都包含更多组的选择,依此类推,直到它们最终命中元素,叶级实际标记,如果你愿意。

小组本身不应该有循环引用; '技巧'出现在any.mix组的无限发生中,即它是一个具有无限根选择的选择树。

相关问题