自己和后续兄弟姐妹的逗号分隔表达式列表在 XPath 中有效,但不适用于 XSLT 匹配模式
comma-separate list of expressions for self and following siblings works in XPath but not as XSLT match pattern
这是一个有效的 XPath 2.0:
//hi[@rend="bold"]/(self::hi, following-sibling::*, following-sibling::text())
它select 具有给定属性的所有 hi 节点以及所有同级元素和文本节点。
但是,如果我尝试像这样在 XSLT 2.0 中使用此 XPath:
<xsl:template match="hi[@rend='bold']/(self::hi, following-sibling::*, following-sibling::text())">
<!--do something-->
</xsl:template>
我遇到语法错误。这是为什么?我怎样才能重写这个匹配模式以便它在 XSLT 中工作?
目标是能够将以上所有内容包装在一个新元素中。
一切顺利,
丁奇
I am getting a syntax error. Why is that?
XSLT 匹配模式 有自己的 syntax rules。只有一部分有效的 XPath 表达式也是有效的匹配模式。
How can I rewrite this matching pattern so that it works in XSLT?
超出我的想象:
<xsl:template match="hi[@rend='bold'] | *[preceding-sibling::hi[@rend='bold']] | text()[preceding-sibling::hi[@rend='bold']]">
可能有更优雅的表达方式,但我相信它确实做到了您所说的。
我就是这样解决上述问题的:
<xsl:template match="hi[@rend='bold']">
<xsl:element name="wrap">
<xsl:element name="hi">
<xsl:attribute name="rend">bold</xsl:attribute>
<xsl:value-of select="."/>
</xsl:element>
<xsl:copy-of select="following-sibling::node()"></xsl:copy-of>
</xsl:element>
</xsl:template>
<xsl:template match="node()[preceding-sibling::hi[@rend='bold']]"></xsl:template>
基本上,我们先匹配hi元素,将它包裹起来,复制它后面的节点;在一个单独的模式中,我们匹配具有特定 hi 元素的节点作为它们的前一个兄弟节点,这样它们的内容就不会在输出中出现两次。
一个重要的教训:您不能只使用任何 xPath 并将其粘贴到您的 XSLT 中。
有时我想将模板规则应用于像这样的复杂模式选择的节点,最好的解决方案是将全局变量绑定到所有相关节点,然后使用模式中的全局变量:
<xsl:variable name="afterBold"
select="//hi[@rend="bold"]/
(self::hi, following-sibling::*, following-sibling::text())"/>
<xsl:template match="node()[. intersect $afterBold]"/>
以上要求 XSLT 2.0。在 XSLT 3.0 中可以简化:
<xsl:template match="$afterBold"/>
这是一个有效的 XPath 2.0:
//hi[@rend="bold"]/(self::hi, following-sibling::*, following-sibling::text())
它select 具有给定属性的所有 hi 节点以及所有同级元素和文本节点。
但是,如果我尝试像这样在 XSLT 2.0 中使用此 XPath:
<xsl:template match="hi[@rend='bold']/(self::hi, following-sibling::*, following-sibling::text())">
<!--do something-->
</xsl:template>
我遇到语法错误。这是为什么?我怎样才能重写这个匹配模式以便它在 XSLT 中工作?
目标是能够将以上所有内容包装在一个新元素中。
一切顺利, 丁奇
I am getting a syntax error. Why is that?
XSLT 匹配模式 有自己的 syntax rules。只有一部分有效的 XPath 表达式也是有效的匹配模式。
How can I rewrite this matching pattern so that it works in XSLT?
超出我的想象:
<xsl:template match="hi[@rend='bold'] | *[preceding-sibling::hi[@rend='bold']] | text()[preceding-sibling::hi[@rend='bold']]">
可能有更优雅的表达方式,但我相信它确实做到了您所说的。
我就是这样解决上述问题的:
<xsl:template match="hi[@rend='bold']">
<xsl:element name="wrap">
<xsl:element name="hi">
<xsl:attribute name="rend">bold</xsl:attribute>
<xsl:value-of select="."/>
</xsl:element>
<xsl:copy-of select="following-sibling::node()"></xsl:copy-of>
</xsl:element>
</xsl:template>
<xsl:template match="node()[preceding-sibling::hi[@rend='bold']]"></xsl:template>
基本上,我们先匹配hi元素,将它包裹起来,复制它后面的节点;在一个单独的模式中,我们匹配具有特定 hi 元素的节点作为它们的前一个兄弟节点,这样它们的内容就不会在输出中出现两次。
一个重要的教训:您不能只使用任何 xPath 并将其粘贴到您的 XSLT 中。
有时我想将模板规则应用于像这样的复杂模式选择的节点,最好的解决方案是将全局变量绑定到所有相关节点,然后使用模式中的全局变量:
<xsl:variable name="afterBold"
select="//hi[@rend="bold"]/
(self::hi, following-sibling::*, following-sibling::text())"/>
<xsl:template match="node()[. intersect $afterBold]"/>
以上要求 XSLT 2.0。在 XSLT 3.0 中可以简化:
<xsl:template match="$afterBold"/>