2010-01-06 53 views
10

我试图实现一个非常简单的XML模式约束。XSD键/ keyref初学者问题

上 类型<巴茨的元件用IDREF属性>只应 允许有匹配 的ID至少一个 元件<酒吧>上属性的值。

如果这对你没有任何意义,那么请看下面的示例XML文档,我认为它比我试图用文字说明更好。

所以,问题:为什么xmllint让下面的schema/xml组合通过(它说文档是有效的)? 如何修复它以实现所需的约束?

的模式:

<?xml version="1.0"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="test" xmlns="test" elementFormDefault="qualified"> 

    <xs:element name="foo"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element name="bar" minOccurs="0" maxOccurs="unbounded"> 
        <xs:complexType> 
         <xs:attribute name="id" use="required" type="xs:string" /> 
        </xs:complexType> 
       </xs:element> 
       <xs:element name="batz" minOccurs="0" maxOccurs="unbounded"> 
        <xs:complexType> 
         <xs:attribute name="idref" use="required" type="xs:string" /> 
        </xs:complexType> 
       </xs:element> 
      </xs:sequence> 
     </xs:complexType> 

     <xs:key name="ID"> 
      <xs:selector xpath="./bar" /> 
      <xs:field xpath="@id" /> 
     </xs:key> 

     <xs:keyref name="IDREF" refer="ID"> 
      <xs:selector xpath="./batz" /> 
      <xs:field xpath="@idref" /> 
     </xs:keyref> 

    </xs:element> 
</xs:schema> 

文件:

<?xml version="1.0"?> 
<foo xmlns="test"> 
    <bar id="1" /> 
    <bar id="2" /> 
    <batz idref="1" /> <!-- this should succeed because <bar id="1"> exists --> 
    <batz idref="3" /> <!-- this should FAIL --> 
</foo> 

回答

2

你的XML文档,如图所示,不包括schemaLocation。当XML文档没有引用模式或DTD时,只需通过格式良好的XML即可通过验证。 (这曾经发生在同事身上,使用了不同的验证器,我认为这是一个错误,验证者没有至少给出它缺少架构或DTD的警告,但我离题了)

反正,它可能应该是这样的:

<?xml version="1.0"?> 
<foo 
    xmlns="test" <!-- This is bad form, by the way... --> 
    xsi:schemaLocation="test /path/to/schema/document" 
    <bar id="1" /> 
    <bar id="2" /> 
    <batz idref="1" /> <!-- this should succeed because <bar id="1"> exists --> 
    <batz idref="3" /> <!-- this should FAIL --> 
</foo> 
+0

谢谢!这是问题所在。 – razorline 2010-01-06 18:24:09

+1

使用它,它仍然在某些验证器中验证。但是当然你需要引用模式。 – 2010-01-06 18:36:25

7

即使使用指定的模式位置,这也不适用于所有解析器。

<?xml version="1.0"?> 
<foo xmlns="test" 
    xsi:schemaLocation="test test.xsd" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <bar id="1" /> 
    <bar id="2" /> 
    <batz idref="1" /> <!-- this should succeed because <bar id="1"> exists --> 
    <batz idref="3" /> <!-- this should FAIL --> 
</foo> 

这也会验证,因为密钥没有引用目标名称空间。

的变化需要在XSD来进行的

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="test" 
    xmlns:t="test" 
    xmlns="test" elementFormDefault="qualified"> 

而且

<xs:key name="ID"> 
    <xs:selector xpath="./t:bar" /> 
    <xs:field xpath="@id" /> 
</xs:key> 

<xs:keyref name="IDREF" refer="ID"> 
    <xs:selector xpath="./t:batz" /> 
    <xs:field xpath="@idref" /> 
</xs:keyref> 

对于讨论关于这种行为看#1545101