基于XML的XSD动态枚举

时间:2013-11-12 23:57:05

标签: xml xsd xsd-validation

说我有以下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因为它们是硬编码的。 有没有办法对元素值进行类似的检查,比如我目前正在使用属性值进行检查?

2 个答案:

答案 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断言之外,我无法看到解决方案。

相关问题