XML架构:需要一个要素是存在当另一个存在

问题描述:

我的架构允许一个特定的元素是可选的,但是当我在文件中遇到不同也可选元素以后,我需要上一个存在。我如何通过XSD确保这一点?XML架构:需要一个要素是存在当另一个存在

实施例:

<settings> 
    <file name="narf.txt"/> 
    <metafile name="narf.meta"/> 
    <filtermeta>true</filtermeta> 
</settings> 

应该是有效的,

<settings> 
    <file name="narf.txt"/> 
    <metafile name="narf.meta"/> 
</settings> 

<settings> 
    <file name="narf.txt"/> 
</settings> 

应该是有效的太,

<settings> 
    <file name="narf.txt"/> 
    <filtermeta>true</filtermeta> 
</settings> 

应该无效。

+0

看起来这是不可能的XML模式1.0 - 未来的规范可能允许IF-THEN-ELSE,至少它正在讨论。 – brandstaetter 2012-01-09 12:58:27

请尝试以下架构定义:

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> 
    <xs:element name="settings"> 
    <xs:complexType> 
     <xs:sequence> 
     <xs:element name="file"> 
      <xs:complexType> 
      <xs:attribute name="name" type="xs:string"/> 
      </xs:complexType> 
     </xs:element> 
     <xs:sequence minOccurs="0"> 
      <xs:element name="metafile"> 
      <xs:complexType> 
       <xs:attribute name="name" type="xs:string"/> 
      </xs:complexType> 
      </xs:element> 
      <xs:element minOccurs="0" name="filtermeta" type="xs:string"/> 
     </xs:sequence> 
     </xs:sequence> 
    </xs:complexType> 
    </xs:element> 
</xs:schema> 

我使用xmllint运行针对该模式的第一个三个例子,他们正确地验证。第四个示例失败:

cvc-complex-type.2.4.a: Invalid content was found starting with element 'filtermeta'. One of '{metafile}' is expected. 

正如预期的那样。

+0

谢谢。虽然这解决了我为解释我的问题而发布的一个简单示例,但它并不能解决潜在的问题,特别是在架构逻辑和层次结构中元素进一步分开的情况下尤其如此。它可能会使代码重复工作,但这只是丑陋的。 – brandstaetter 2012-01-10 07:44:05

+1

同意。对于更一般的情况,它会迅速变得非常不愉快。像Schematron这样的东西在这里会更好 - 你可以放松XSD,这样它就可以关注基本结构和输入约束。然后,'交叉字段'验证规则(例如,如果元素'A'存在,元素'B'必须存在)可以写为Schematron规则。 – 2012-01-10 15:54:01

+0

例如,可以编写一个Schematron规则对提供的测试的情况下为: ' 如果filtermeta存在,元文件也必须存在 ' – 2012-01-10 15:59:01

你可以有filtermeta作为一个可选属性为metafile元素。