检测XSL中的模板优先级冲突

时间:2015-10-28 22:16:29

标签: xslt xslt-1.0

我有一个XSL样式表,它可以导入许多其他XSL样式表,并用于处理各种XML文件。我想检查一下导入的模板都没有冲突。

例如,我有一个导出import_one.xslimport_two.xsl的样式表。

import_one.xsl包含一个模板:

<xsl:template match="Foo">
   One
</xsl:template>

import_two.xsl包含一个模板:

<xsl:template match="Foo">
    Two
</xsl:template>

这两个模板都将匹配具有相同优先级的Foo个元素,这是XSL处理器可以使用最后导入的模板恢复的错误。

对于给定的一组XML文件,我想检查是否会发生此类错误。

XSL样式表包含JavaScript函数并使用MSXSL节点集,这阻止我使用例如撒克逊人会在发生此类冲突时发出警告。 MSXSL处理器可以处理样式表,但不会发出警告。

我有什么选择?

1 个答案:

答案 0 :(得分:0)

我认为您可能需要考虑编写一些简单的分析工具。这就是XSLT使用XML语法的事实真正开始带来好处:操纵XSLT代码比在大多数其他语言中操作代码要容易得多。如果您只需要了解相同的匹配模式,那么您可以使用类似

的2.0样式表来分析代码。
<xsl:function name="f:all-modules" as="document-node()*">
  <xsl:param name="root" as="document-node()"/>
  <xsl:sequence select="$root, document($root/*/(xsl:include|xsl:import)/@href)/f:all-modules(.)"/>
</xsl:function>

<xsl:template name="duplicate-patterns">
  <xsl:for-each-group select="f:all-modules(.)//xsl:template" 
        group-by="@match">
    <xsl:if test="current-group()[2]">
      <xsl:copy-of select="current-group()"/>
    </xsl:if>
  </xsl:for-each-group>
</xsl:template>

如果你想检测&#34;重叠&#34;有多个匹配的模式(例如para[1]para[@class='header'])则无法通过静态分析完成,您需要进行一些动态处理。一种方法可能是将现有样式表转换为XSLT 2.0样式表,该样式表针对每个模式测试每个元素。您可以通过为每个模式生成唯一模式来完成此操作。它可能看起来像这样:

<xsl:template match="para[1]" mode="mode-7826">1</xsl:template>
<xsl:template match="*" mode="mode-7826"/>

<xsl:template match="para[@class='header']" mode="mode-7827" as="xs:integer">1</xsl:template>
<xsl:template match="*" mode="mode-7827"/>

<xsl:template match="/">
    <xsl:for-each select="//*">
      <xsl:variable name="matches">
        <xsl:apply-templates select="." mode="mode-7826"/>
        <xsl:apply-templates select="." mode="mode-7827"/>
        <xsl:apply-templates select="." mode="mode-7828"/>
        ....
      </xsl:variable>
      <xsl:if test="string-length($matches) gt 1">
        Conflict!!
      </xsl:if>
    </xsl:for-each>
</xsl:template>