1

假设我有以下 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 name="Paul">
  <read writtenBy="Thomson">A writing the author never wrote</read>
</reader>

我能做的是通过使用键和 keyrefs 限制属性可以根据先前定义的属性获取的值(请参阅接受的答案)。基于此,我可以确保“writtenBy”属性实际上是指作者的姓名,或者写作的流派属性来自先前定义的流派。

我知道您可以在 XSD 文档上对枚举进行硬编码(请参阅接受的答案)。
此外,您可以使用断言(在 XSD 1.1 中)根据 XML 中包含的信息进行更灵活的枚举(请参阅接受的答案)。
但我不能使用这些方法,因为它们是硬编码的。有没有办法对元素值进行类似的检查,就像我目前正在使用属性值一样?

4

2 回答 2

1

如果我正确理解您的要求,key/keyref 几乎可以处理它。在共同祖先(根)的级别,您可能希望定义一个键

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

于 2013-11-13T08:11:37.660 回答
1

有几种可能性。首先,您可以使用 key 和 keyref 做一些聪明的事情,检查read元素的内容是否是writing适当作者的元素内容。

但是,给每个写入一个 ID 并让read元素引用该 ID 会更简单。如果消除了冗余,就消除了检查一致性的需要。当然,出于显示目的,您总是可以使用 XSLT 来获取作者姓名和著作。

如果您无法进一步推动 key 和 keyref,并且您不想消除 XML 表示中的冗余,那么检查您指定的约束的最简单方法是使用断言,无论是在 XSD 1.1 中还是在 Schematron 中。

其中,我推荐第二种(重组 XML 以使有效性约束更简单、更容易检查)。当然,您的偏好可能会有所不同。

于 2013-11-13T01:54:43.337 回答