XML架构:忽略具有外部命名空间的标记



假设我有以下xml文档:

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

标签B只能位于标签a内部。我可以编写一个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>

正如您所看到的,标签B现在嵌套在其他没有名称空间的标签中。

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

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

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

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

XSD 1.1目前受到部分但并非所有XSD验证器的支持。

最新更新