如何避免两个不同元素的歧义匹配
How to avoid ambiguous match for two different elements
请建议避免“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]
一般来说,如果您收到该警告(来自 Saxon?),它会准确告诉您匹配了哪两个模板,并在转换示例时采用最后一个模板。如果这给了你正确的结果并且你不想要那个警告,你可以在 xsl:template
上设置一个明确的 priority="5"
例如,5
是一个大于可能计算的示例数字优先事项 http://www.w3.org/TR/xslt20/#conflict。或者您必须更改匹配模式以确保不会同时匹配那个 mi
元素,这是否可能和有意义取决于您的要求,我还没有完全理解。
只有您知道这两个规则在什么情况下应该触发。我从你的样本中猜测,如果某物有一个 msub 祖先,那么你不关心它也有一个 mfrag 祖先的事实。如果是这种情况,那么您的第一条规则优先,最简单的解决方案是使用显式 "priority" 属性赋予它更高的优先级。另一种方法是将模式更改为互斥的,这可能意味着向第二条规则添加谓词 [not(ancestor::msub)]
- 但我会选择明确的优先级。
请建议避免“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]
一般来说,如果您收到该警告(来自 Saxon?),它会准确告诉您匹配了哪两个模板,并在转换示例时采用最后一个模板。如果这给了你正确的结果并且你不想要那个警告,你可以在 xsl:template
上设置一个明确的 priority="5"
例如,5
是一个大于可能计算的示例数字优先事项 http://www.w3.org/TR/xslt20/#conflict。或者您必须更改匹配模式以确保不会同时匹配那个 mi
元素,这是否可能和有意义取决于您的要求,我还没有完全理解。
只有您知道这两个规则在什么情况下应该触发。我从你的样本中猜测,如果某物有一个 msub 祖先,那么你不关心它也有一个 mfrag 祖先的事实。如果是这种情况,那么您的第一条规则优先,最简单的解决方案是使用显式 "priority" 属性赋予它更高的优先级。另一种方法是将模式更改为互斥的,这可能意味着向第二条规则添加谓词 [not(ancestor::msub)]
- 但我会选择明确的优先级。