我的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”,如果还有其他标题,则需要具有此属性。
答案 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 PsychoPath和Saxon的支持),并且不想向您隐瞒。我们的想法是简单地保留属性可选,但要断言第一个项是否设置了它。我不确定这是否可以更简单地表达,但这里有:
<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>
如果你想测试至少一个没有@lang
的标题而其余标题必须有lang
属性,那么你可以写这个(删除另一个断言):
<xs:assert test="count(t:title[not(@lang)]) = 1" />