4 回答
您的要求是识别上下文无关语言。您不能使用模式语言中的内容模型来做到这一点,它要求内容模型是正则表达式,因此需要定义常规而非上下文无关的语言。目前广泛使用的模式语言都不允许内容模型定义上下文无关语言。
您的选择是 (1) 更改您的设计以更好地使用您掌握的技术,而不是反对它,(2) 使用临时流程(如 InfantPro'Aravind' 建议的 XSLT 样式表),或 (3) 使用Schematron 或 XSD 1.1 中的断言来强制执行约束。
InfantPro'Aravind' 错误地指出:
This is not possible with XSD 1.0. I think not possible with 1.1 as well.
事实上,使用 XSD 1.1 断言是很有可能的。只需定义一个内容模型,允许任意数量的 As 后跟任意数量的 B,然后添加断言
<xs:assert test="count(A) = count(B)"/>
这在 XSD 1.0 中是不可能的。我认为 1.1 也是不可能的。
还有其他方法,例如 Schematron。或者可以使用 XSLT 转换并输出结果。反过来可以验证 XML 是否有效。
我将简要介绍第二种方法:
示例输入 XML:
<?xml version="1.0" encoding="utf-8"?>
<root>
<a/>
<a/>
<b/>
<b/>
</root>
示例 XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/root">
<validation>
<xsl:choose>
<!--Output 'true' if count is equal .. and 'false' otherwise-->
<xsl:when test="count(a)=count(b)">
<xsl:text>true</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>false</xsl:text>
</xsl:otherwise>
</xsl:choose>
</validation>
</xsl:template>
</xsl:stylesheet>
由于 count(a) 等于 count(b) 这输出:
<?xml version="1.0" encoding="utf-8"?>
<validation>true</validation>
这反过来将被验证:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="validation" type="xs:boolean" fixed="true"/>
</xs:schema>
在这种情况下将通过,因为<validation>
节点具有价值true
注意:XSLT 只是创建一个我用于扩展验证的转换副本,它不会修改原始输入。
XML Schema 1.0 仅对上下文无关文法提供部分支持。遗憾的是,它不支持需要相等数量的 a 和 b 的语法。另一方面,它确实支持一些上下文无关的语法。我写了一篇文章解释了这一点:http ://www.xfront.com/XML-Schema-1-0-and-Relax-NG-Partially-Support-Context-Free-Grammars.pdf