【问题标题】:Why does this XML validate with this schema?为什么此 XML 使用此架构进行验证?
【发布时间】:2019-11-22 16:45:45
【问题描述】:

一个简单的 XML:

<?xml version="1.0"?>
<root>
 <code>
  <command name="EXPORT"/>
 </code>
 <module name="DEMO_">
  <keyword name="TEST123"/>
 </module>
 <!--
 <code>
   <command name="321TEST" foo="bar"/>
   <keyword name="TEST123"/>
 </code>
 -->
</root>

还有一个简单的架构:

<?xml version='1.0'?>
<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>

 <xs:simpleType name='name'>
  <xs:restriction base='xs:string'>
   <xs:pattern value='[A-Z]*'/>
  </xs:restriction>
 </xs:simpleType>

 <xs:element name='root'>
  <xs:complexType>
   <xs:choice minOccurs='0' maxOccurs='unbounded'>
    <xs:element name='module'/>
    <xs:element name='code'/>
   </xs:choice>
  </xs:complexType>
 </xs:element>

 <xs:element name='code'>
  <xs:complexType>
   <xs:choice minOccurs='0' maxOccurs='unbounded'>
    <xs:element name='command'/>
   </xs:choice>
  </xs:complexType>
 </xs:element>

 <xs:element name='command'>
  <xs:complexType>
   <xs:attribute name='name' type='name' use='required'/>
  </xs:complexType>
 </xs:element>

 <xs:element name='module'>
  <xs:complexType>
   <xs:attribute name='name' type='name' use='required'/>
  </xs:complexType>
 </xs:element>

</xs:schema>

&lt;root&gt; 中允许有任意数量的&lt;code&gt;&lt;module&gt;&lt;code&gt; 可以包含任意数量的&lt;command&gt;&lt;command&gt;&lt;module&gt; 有一个必需的属性 name,它必须只包含大写字母。就是这样。

上面的 XML 被这个架构错误:

  • &lt;module&gt; 元素的name 包含下划线。
  • &lt;module&gt; 元素包含一个从未定义或允许的&lt;keyword&gt; 元素。

但是xmllinthttps://www.liquid-technologies.com/online-xsd-validator(至少)仍然说它是有效的:

$ xmllint --schema test.xsd test.xml --noout
test.xml validates

我错过了什么?

如果我取消注释最后一个元素,我会收到无效 name 和不允许的属性 foo 的错误(但仍然不是 &lt;keyword&gt; 元素)。这样就完成了某种验证。

【问题讨论】:

    标签: xml validation xsd


    【解决方案1】:

    您的错误(常见错误)是在内容模型中使用&lt;xs:element name="ABC"/&gt;,而您原本打算使用&lt;xs:element ref="ABC"/&gt;。您的架构是合法的,但是您定义了没有关联类型的局部元素声明,而不是引用具有关联类型的全局元素声明。

    【讨论】:

      【解决方案2】:

      在架构中,您已指定根元素可能包含任意数量的模块或代码元素,但您尚未指定这些元素的类型。

      我不确定您要为 XML 文档实施什么结构。一种可能性可能是以下模式,其中根元素内的模块和代码元素具有非常特定的结构:

      <?xml version='1.0'?>
      <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>
      
          <xs:simpleType name='name'>
              <xs:restriction base='xs:string'>
                  <xs:pattern value='[A-Z]*'/>
              </xs:restriction>
          </xs:simpleType>
      
          <xs:element name='root'>
              <xs:complexType>
                  <xs:choice minOccurs='0' maxOccurs='unbounded'>
                      <xs:element name='module' type ="moduleType"/>
                      <xs:element name='code' type="codeType"/>
                  </xs:choice>
              </xs:complexType>
          </xs:element>
      
          <xs:element name='code' type="codeType"/>
          <xs:element name='command' type="commandType"/>
          <xs:element name='module' type="moduleType"/>
      
          <xs:complexType name="codeType">
              <xs:choice minOccurs='0' maxOccurs='unbounded'>
                  <xs:element name='command'/>
              </xs:choice>
          </xs:complexType>
      
          <xs:complexType name="commandType">
              <xs:attribute name='name' type='name' use='required'/>
          </xs:complexType>
      
          <xs:complexType name="moduleType">
              <xs:attribute name='name' type='name' use='required'/>
          </xs:complexType>
      
      </xs:schema>
      

      如果您尝试根据此架构验证您的 XML 文档,您会发现(以及其他验证错误)值“DEMO_”无效。

      【讨论】:

      • &lt;element&gt; 内部的&lt;complexType&gt; 不是指定类型吗,就像在“根”元素中一样?我知道 XML 文档无效,这就是重点,如果通过了错误的文档,我不能依赖模式。
      • 确实为“根”元素指定了一个类型。它指定“根”元素包含任意数量的名为“代码”或“模块”的元素。但是,尚未指定根元素内的“代码”和“模块”元素的类型。这些元素与模式中稍后的“代码”和“模块”元素的定义“分离”。你可以按照我的建议或@Michael Kay 的建议来纠正这个问题。顺便说一句,使用 xml 模式的主要目的是检测“错误”文档并确保它们不会通过。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-03
      • 1970-01-01
      相关资源
      最近更新 更多