假设我有以下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)中用于约束元素内容的内容模型定义了子元素的合法序列;它们的工作方式就像上下文无关语法中的单个生成规则。可以在更深层次约束子体,但这需要一个完整的声明链:在您的示例中,当foo
和bar
出现在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验证器的支持。