说我有以下XML文档:
<root>
<genres>
<genre name="comedy" />
<genre name="academic" />
</genres>
<authors>
<author name="Thomson">
<writings>
<writing genre="academic">The text book</writing>
<writing genre="comedy">The worst comedy</writing>
<writings>
</author>
</authors>
<readers>
<reader name="Phil">
<read writenBy="Thomson">The text book</read>
</reader>
<reader name="John" />
</readers>
</root>
正如您所看到的,'reader'元素可能没有'read'孩子。
但是,我希望验证过程确保没有类似的条目:
<reader name="Paul">
<read writtenBy="Thomson">A writing the author never wrote</read>
</reader>
我可以做的是通过使用keys和keyrefs来限制属性可以根据先前定义的属性获取的值(请参阅accepted answer)。基于此,我可以确保'writtenBy'属性实际上是指作者的名字,或者写作的类型属性来自之前定义的类型。
我知道你可以在XSD文档上硬编码枚举(参见accepted answer)。
此外,您可以使用断言(在XSD 1.1中)根据XML中包含的信息(参见accepted answer)获得更灵活的枚举。
但我不能使用这些apporaches因为它们是硬编码的。 有没有办法对元素值进行类似的检查,比如我目前正在使用属性值进行检查?
答案 0 :(得分:1)
有几种可能性。首先,您可以使用key和keyref做一些聪明的事情,它会检查read
元素的内容是否是相应作者的writing
元素的内容。
但是,给每个写入一个ID更简单,只需让read
元素引用该ID即可。如果消除冗余,则无需检查一致性。当然,出于显示目的,您始终可以使用XSLT来获取作者的姓名和写作。
如果你不能再推送key和keyref,并且你不想消除XML表示中的冗余,那么检查你指定的约束的最简单方法是使用XSD 1.1中的断言或者在Schematron。
其中,我推荐第二个(重构XML以使有效性约束更简单,更容易检查)。当然,您的偏好可能会有所不同。
答案 1 :(得分:1)
如果我理解你的要求正确,key / keyref可以 ALMOST 处理它。在共同祖先(root)的级别,您可能希望使用
定义键* selector = authors/author/writings/writing
* fields =
(a) ../../@name
(b) .
并使用
定义keyref* selector = readers/reader/read
* fields =
(a) @writtenBy
(b) .
唯一的问题是你不能使用../../@name
- 你不能在密钥和keyrefs允许的XPath子集中引用祖先的属性。除了(a)更改XML设计以在“writing”元素中复制作者姓名,或(b)使用XSD 1.1断言之外,我无法看到解决方案。