如何避免两个不同元素的模糊匹配

时间:2015-02-02 16:26:51

标签: xml xslt xslt-2.0

请建议避免“ mfrac ”和“ msub ”元素的模糊模板匹配。这里对脚本进行编码以删除

中存在的“Space1”文本节点
  • msub的第一个或第二个孩子或带有第一个文本节点的mfrac
  • msub或mfrac的第一个或第二个孩子,最后一个文本节点

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

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]

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:2)

一般情况下,如果你得到那个警告(来自Saxon?),它会准确地告诉你哪两个匹配的模板,以及转换样本时最后一个模板。如果这样可以得到正确的结果并且您不希望出现该警告,则可以在priority="5"上设置明确的xsl:template5是一个大于可能计算的示例数字优先事项http://www.w3.org/TR/xslt20/#conflict。或者你必须改变你的匹配模式,以确保两者都不匹配mi元素,这是否可行并且有意义取决于你还没有完全理解的要求。