如何避免两个不同元素的歧义匹配

How to avoid ambiguous match for two different elements

请建议避免“mfrac”和“msub”元素的模棱两可的模板匹配。这里的脚本被编码为删除出现在

的 'Space1' 文本节点

注意:能够获得所需的结果,但得到可恢复的错误信息。

XML:(注释为解释需求,非真实)

<article>
    <disp-formula id="eqn1">
        <math>
            <mfrac>
                <mrow>
                    <msub>
                        <mrow>
                            <mi mathcolor1="blue">Space1</mi><!--Remove: FRAC's First Child's very first text node (even thou it is under MSUB, but with respect to MFRAC should not have SPACE as  -->
                                <mi>H</mi>
                            <mi mathcolor1="blue">Space1</mi><!--Remove: SUB's First Child's last text node -->
                        </mrow>
                        <mrow>
                            <mi mathcolor1="blue">Space1</mi><!--Remove: SUB's Second Child's very first text node -->
                                <mn>2</mn>
                            <mi mathcolor1="blue">Space1</mi><!--Remove: SUB's Second Child's last text node -->
                        </mrow>
                    </msub>
                </mrow>
                <mfenced>
                    <mi mathcolor1="blue">Space1</mi><!--Remove: FRAC's Second Child's very first text node -->
                       <mrow><mi>2</mi></mrow>
                    <mi mathcolor1="blue">Space1</mi><!--Remove: FRAC's Second Child's last text node -->
                </mfenced>
            </mfrac>
        </math>
    </disp-formula>
</article>

XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="@*|node()">
            <xsl:copy><xsl:apply-templates select="@* | node()"/></xsl:copy>
    </xsl:template>

    <xsl:template match="msub/*[count(preceding-sibling::*)=1]//mi[@mathcolor1][contains(.,'Space1')]"><!--SUB space at end and before of SUBSCRIPT text -->
        <xsl:variable name="varPreceded1"><xsl:value-of select="preceding::text()[normalize-space(.)!='']
            [1][generate-id(ancestor::*[count(preceding-sibling::*)=1]/parent::msub)=generate-id(current()/ancestor::*[count(preceding-sibling::*)=1]/parent::msub)]"/></xsl:variable>
        <xsl:variable name="varFollowed1"><xsl:value-of select="following::text()[normalize-space(.)!='']
            [1][generate-id(ancestor::*[count(preceding-sibling::*)=1]/parent::msub)=generate-id(current()/ancestor::*[count(preceding-sibling::*)=1]/parent::msub)]"/></xsl:variable>

                    <xsl:choose>
                        <xsl:when  test="string-length($varFollowed1) eq 0"><remove2/></xsl:when>
                        <xsl:when  test="string-length($varPreceded1) eq 0"><remove1/></xsl:when>
                        <xsl:otherwise><xsl:copy><xsl:apply-templates select="@* | node()"/></xsl:copy></xsl:otherwise>
                    </xsl:choose>
    </xsl:template>

    <xsl:template match="mfrac/*[count(preceding-sibling::*)=0]//mi[@mathcolor1][contains(.,'Space1')]"><!--FRAC space at begin end of NUMERATOR text -->
        <xsl:variable name="varPreceded1"><xsl:value-of select="preceding::text()[normalize-space(.)!='']
            [1][generate-id(ancestor::*[count(preceding-sibling::*)=0]/parent::mfrac)=generate-id(current()/ancestor::*[count(preceding-sibling::*)=0]/parent::mfrac)]"/></xsl:variable>
        <xsl:variable name="varFollowed1"><xsl:value-of select="following::text()[normalize-space(.)!='']
            [1][generate-id(ancestor::*[count(preceding-sibling::*)=0]/parent::mfrac)=generate-id(current()/ancestor::*[count(preceding-sibling::*)=0]/parent::mfrac)]"/></xsl:variable>

                    <xsl:choose>
                        <xsl:when  test="string-length($varFollowed1) eq 0"><remove2/></xsl:when>
                        <xsl:when  test="string-length($varPreceded1) eq 0"><remove1/></xsl:when>
                        <xsl:otherwise><xsl:copy><xsl:apply-templates select="@* | node()"/></xsl:copy></xsl:otherwise>
                    </xsl:choose>
    </xsl:template>


</xsl:stylesheet> 

错误信息:

Recoverable error
  XTRE0540: Ambiguous rule match for
  /article/disp-formula[1]/math[1]/mfrac[1]/mrow[1]/msub[1]/mrow[1]/mi[3]

一般来说,如果您收到该警告(来自 Saxon?),它会准确告诉您匹配了哪两个模板,并在转换示例时采用最后一个模板。如果这给了你正确的结果并且你不想要那个警告,你可以在 xsl:template 上设置一个明确的 priority="5" 例如,5 是一个大于可能计算的示例数字优先事项 http://www.w3.org/TR/xslt20/#conflict。或者您必须更改匹配模式以确保不会同时匹配那个 mi 元素,这是否可能和有意义取决于您的要求,我还没有完全理解。

只有您知道这两个规则在什么情况下应该触发。我从你的样本中猜测,如果某物有一个 msub 祖先,那么你不关心它也有一个 mfrag 祖先的事实。如果是这种情况,那么您的第一条规则优先,最简单的解决方案是使用显式 "priority" 属性赋予它更高的优先级。另一种方法是将模式更改为互斥的,这可能意味着向第二条规则添加谓词 [not(ancestor::msub)] - 但我会选择明确的优先级。