首页 > 解决方案 > 使用递归 XML 模式进行验证未在嵌套元素中找到预期的错误

问题描述

我创建了一个具有长递归路径的 XML 模式:

Rectangle->Rectangle_t->Content_t->TopContent_t->[Rectangle or TextBlock]

其中以“_t”结尾的名称是类型,而不是元素。我正在使用一个带有动态验证的 XML 编辑器,它知道 aTextBlock是允许在Rectangle. 但它不会抱怨嵌套的无效属性TextBlock(它确实在 的同级上捕获它们Rectangle)。我使用了多个验证器来确保它不仅仅是 XML 编辑器中的一个缺陷。

所以这里是模式(为它的长度道歉,它实际上归结为一些):

<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <!-- definition of attributes -->
  <xs:attribute name="Name" type="xs:string"/>
  <xs:attribute name="Height" type="xs:integer"/>
  <xs:attribute name="Width" type="xs:integer"/>
  <xs:attribute name="Top" type="xs:integer"/>
  <xs:attribute name="Left" type="xs:integer"/>
  <xs:attribute name="Text" type="xs:string"/>

  <xs:attributeGroup name="Element">
    <xs:attribute ref="Name"/>
    <xs:attribute ref="Top" />
    <xs:attribute ref="Left" />
  </xs:attributeGroup>

  <!-- definition of complex elements -->
  <xs:complexType name="TopContent_t">
    <xs:choice maxOccurs="unbounded">
      <xs:element name="Rectangle" minOccurs="0" maxOccurs="unbounded" />
      <xs:element name="TextBlock" minOccurs="0" maxOccurs="unbounded" />
    </xs:choice>
  </xs:complexType>

  <xs:element name="Project">
    <xs:complexType>
      <xs:choice minOccurs="1" maxOccurs="unbounded">
        <xs:element name="Component" maxOccurs="unbounded" />
        <xs:element name="Image" maxOccurs="unbounded" />
      </xs:choice>
    </xs:complexType>
  </xs:element>

  <xs:complexType name="Component_t">
    <xs:complexContent>
      <xs:extension base="TopContent_t">
        <xs:attribute ref="Name" use="required"/>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:element name="Component" type="Component_t" />

  <xs:complexType name="Image_t">
    <xs:complexContent>
      <xs:extension base="TopContent_t">
        <xs:attribute ref="Name" use="required"/>
        <xs:attribute ref="Height" use="required"/>
        <xs:attribute ref="Width" use="required"/>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:element name="Image" type="Image_t" />

  <xs:complexType name="Content_t">
    <xs:complexContent>
      <xs:extension base="TopContent_t">
        <xs:attributeGroup ref="Element" />
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="Rectangle_t">
    <xs:complexContent>
      <xs:extension base="Content_t">
        <xs:attribute ref="Height" use="required" />
        <xs:attribute ref="Width" use="required" />
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:element name="Rectangle" type="Rectangle_t" />

  <xs:element name="TextBlock">
    <xs:complexType>
      <xs:attributeGroup ref="Element" />
      <xs:attribute ref="Text" />
    </xs:complexType>
  </xs:element>
    
</xs:schema>

这里作为一个 XML 文件,它认为是有效的,但不应该是:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ScreenDesigner.xsd">
    <Image Name="Main Screen" Width="200" Height="250" Fill="White">
        <Rectangle Name="Box" Width="30" Height="30">
            <TextBlock foo="bar" ></TextBlock>
        </Rectangle>
        <TextBlock Text="testing"></TextBlock>
        <Image Name="Not allowed" Height="0" Width="0"></Image>
    </Image>
</Project>

TexBlock嵌套在 中的Rectangle属性“foo”应该被标记为错误,但不是。如果我将该属性放在 external 上TextBlock,它会被标记。此外,它允许一个Image内部的Image,这也应该是一个错误。

这是我第一次尝试创建 XML 模式,如果能帮助我找出我做错了什么,我将不胜感激。

标签: xmlschema

解决方案


当我通过 Saxon 的模式验证器运行它时,我收到了表单的警告

Warning at xs:element on line 21 column 74 of test.xsd:
   Local element declaration matches the name of a global element, and allows any content.
  Did you mean to write ref='Rectangle' instead of name='Rectangle'? To suppress this
  warning, add type='xs:anyType'

这些警告是解决问题的关键。当您编写<xs:element name="Rectangle">没有type属性时,您定义的是允许任何内容的本地元素声明,而不是引用限制内容的全局元素声明。一个容易犯的错误,因此发出警告。


推荐阅读