XSD文件确保一个无限次出现的元素的属性没有设置一次?

时间:2015-09-11 14:56:59

标签: xml xsd schema

我的xml文件包含一个带有可选属性lang的元素。

e.g。

<movie>
    <title>Lord of the Rings</title>
    <title lang="ger">Herr der Ringe</title>
    <title lang="esp">El Senor de los Anillos</title>
</movie>
<movie>
    <title>Game of Thrones</title>
</movie>
<movie>
    <title>Star War</title>
    <title lang="fra">Guerre des etoiles</title>
    <title lang="ger">Krieg der Sterne</title>
</movie>

有没有办法在xml架构中确保每部电影都只有一部没有任何属性“lang”,如果还有其他标题,则需要具有此属性。

2 个答案:

答案 0 :(得分:1)

它不是你要求的,但它可能是你想要的:我认为你可以通过定义属性的默认值来处理这个问题(例如&#34; en&#34;)和然后检查所有值是否唯一。您可以在xs:attribute声明中定义默认值,并且可以使用

movie元素的声明中定义唯一性
<xs:unique name="unique-lang">
  <xs:selector xpath="title"/>
  <xs:field xpath="@lang"/>
</xs:unique>

这不会停止在标题的英文版本上明确显示的默认值,但我认为你可以接受它。

我建议使用语言的国际标准代码,而不是自己编写代码。

答案 1 :(得分:1)

我喜欢Michael Kay的方法,很简单。

虽然与此同时我尝试使用xs:assert的方法(警告:需要XSD 1.1,但这得到at least Xerces, with PsychoPathSaxon的支持),并且不想向您隐瞒。我们的想法是简单地保留属性可选,但要断言第一个项是否设置了它。我不确定这是否可以更简单地表达,但这里有:

<xs:element name="movie" type="t:tpMovie" />

<xs:complexType name="tpMovie">
    <xs:sequence>            
        <xs:element name="title"  minOccurs="1" type="t:tpTitle" maxOccurs="unbounded">
        </xs:element>
    </xs:sequence>        
    <xs:assert test="t:title[1][not(@lang)]" />
    <xs:assert test="every $t in t:title[1]/following-sibling::t:title satisfies not(empty($t/@lang))" />
</xs:complexType>

<xs:complexType name="tpTitle">
    <xs:attribute name="lang" use="optional"/>
</xs:complexType>

使用以下输入:

<movie .. ns removed for brevity..>    
    <title />
    <title lang="en"/>
    <title lang="es" />
    <title  />
</movie>

或:

<movie ..ns removed for brevity..>    
    <title lang="de"/>
    <title lang="en"/>
    <title lang="es" />
</movie>

您将收到断言错误。

以下成功:

<movie ..ns removed for brevity..>    
    <title />
    <title lang="de"/>
    <title lang="en"/>
    <title lang="es" />
</movie>

更新(新请求,请参阅comment

如果你想测试至少一个没有@lang的标题而其余标题必须有lang属性,那么你可以写这个(删除另一个断言):

<xs:assert test="count(t:title[not(@lang)]) = 1" />