【问题标题】:In XSD, can I set mandatory child elements based on parent element's content?在 XSD 中,我可以根据父元素的内容设置强制子元素吗?
【发布时间】:2012-01-15 21:40:23
【问题描述】:

我有一个 XML 和 XSD 耦合,其中包括类似于以下内容的“House”元素:

<root>
...
<House>
    <id>1</id>
    <type>Cottage</type>
    <imageSrc> image.jpg </imageSrc>
</House>
<House>
    <id>2</id>
    <type>Private</type>
</House>    

我想通过我的 XSD 强制要求所有类型为“Cottage”的房屋都必须有一个强制标签,但其他房屋没有。 (或者相反 - 唯一的“私人”。有没有办法做到这一点?

【问题讨论】:

  • 更正:XSD 1.0 无法做到这一点。 XSD 1.1 可以。

标签: xml xsd


【解决方案1】:

您可能需要考虑使用Schematron 之类的东西来表达这些超出XML Schema 功能的附加验证规则。 Schematron 是一个开放 (ISO) 标准,它允许您表达关于应该出现在 XML 文档中的模式的断言。例如,您可以使用它来表达约束,例如:

  • 如果存在元素A,则禁止元素B。如果 AB 是同级元素,您可以在 XML 架构中使用 xs:choice 来执行此操作,但如果这两个元素不是同级元素,则此方法在 XML 架构中不起作用。
  • 如果元素A有一个具有特定值的属性,那么它必须包含子元素B
  • 元素A必须等于元素BC的总和。

在您的具体示例中,我将假设 imageSrc 是您希望在“山寨”类型的房屋上强制其存在并禁止其他人出现的强制性标签。

表达这些断言的简单 Schematron 模式示例如下:

<schema xmlns="http://purl.oclc.org/dsdl/schematron">
  <pattern>
    <!-- Houses of type 'Cottage' must contain an imageSrc element -->
    <rule context = "/root/House[type/text() = 'Cottage']">
      <assert test = "imageSrc">Cottages must have an image</assert>
    </rule>

    <!-- Houses not of type 'Cottage' must not contain an imageSrc element -->
    <rule context = "/root/House[type/text() != 'Cottage']">
      <assert test = "not(imageSrc)">Non-cottages must not have an image</assert>
    </rule>
  </pattern>
</schema>

在这里,我将模式表示为两个单独的规则,一个用于您需求的两个部分。

每个rule 都有一个context 属性,它是一个XPath 表达式。当此表达式计算为真时,规则“触发”。因此,第一条规则会触发具有 type 子元素的 House 元素,其文本内容等于“Cottage”。

当规则触发时,通过评估assert 元素的test 属性来检查断言。同样,这是一个 XPath 表达式,但用于评估测试表达式的上下文节点是与 rule 元素匹配的节点(在本例中为 House)。当测试表达式计算结果为真时,断言通过(即文档对于此断言有效)。如果它评估为假,则断言失败。 assert 元素的文本内容通常是可以传递给最终用户的断言的人类可读描述。 Schematron 还提供了额外的工具(称为“诊断”)以将额外的技术消息链接到断言。

可通过http://www.schematron.com/implementation.html 获得公开可用的基于 XSLT 的 Schematron 实现。典型的验证管道将首先针对定义文档基本结构要求(例如元素层次结构、基数、数据类型、模式等)的 XML Schema 验证文档。然后,一旦文档通过了这个基本级别的验证,您就可以根据 Schematron 模式验证文档,以验证其他基于模式的约束。该管道可以以编程方式实现,或者使用(例如)批处理文件、Ant 脚本或XProc 处理器。

【讨论】:

    【解决方案2】:

    虽然 XSD 确实不支持这种行为,但您可以简单地定义两种 House 类型,一种带有强制节点,一种没有。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-03
      相关资源
      最近更新 更多