0

假设我有以下 xml 文档:

<root xmlns:p="uri:myNamespace">
  <p:tagA>
    <p:tagB />
  </p:tagA>
</root>

tagB 只能在 tagA 内。我可以编写一个 xsd 来验证:

<xsd:schema ... targetNamespace="uri:myNamespace" elementFormDefault="qualified">
  <xsd:element name="tagA">
    <xsd:complexType>
      <xsd:element name="tagB" type="..." />
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

现在问题来了:我想忽略外部命名空间之间的任何标签:

<root xmlns:p="uri:myNamespace">
  <p:tagA>
    <whatever />
    <foo>
      <bar>
        <p:tagB />
      </bar>
    </foo>
  </p:tagA>
</root>

如您所见, tagB 现在嵌套在没有命名空间的其他标签中。

是否有可能(如何?)编写一个 XSD,它仍然强制tagA我的命名空间中的唯一标签是 atagB但中间可能有其他命名空间的任何标签?

4

1 回答 1

0

XSD(以及 DTD 和 Relax NG)中用于约束元素内容的内容模型定义了子元素的合法序列;它们就像上下文无关语法中的单一生产规则一样工作。可以在更深层次上约束后代,但它需要一个完整的声明链:在您的示例中,您需要声明foo它们bar何时出现在一个p:tagA元素中,以确保它们之间恰好包含一个p:tagB元素。但是您的出发点是您不想限制这些元素。

所以:你不能使用内容模型来表达你心中的约束。

在 XSD 1.1 中,您可以使用附加到p:tagA元素的断言来要求它p:tagB在其后代中准确包含一个元素 ( count(.//p:tagB) eq 1)。但是,您不能使用附加到的断言p:tagB来要求它只出现在p:tagA元素中:断言可以在树中向下看,但不能向上看。(如果您知道保证存在的容器的名称,则可以在该容器上使用断言,断言每个 p:tagB 元素都包含在 ap:tagA 元素中,使用类似的断言count(.//p:tagA//p:tagB) eq count(.//p:tagB)。)

XSD 1.1 目前由一些但不是所有 XSD 验证器支持。

于 2013-08-15T15:35:46.633 回答