XSLT技术咨询:如何选取指定节点后目标节点并遇特定节点终止
我来帮你搞定这个XSLT节点选择的问题~你需要的是从<p class="busta"/>之后开始,选取所有<p class="dialogo"/>,但碰到<p class="capo"/>就立刻停止,不能再选后面的dialogo。之前的代码逻辑没把范围限制住,所以才错误选中了dialogo 6。
解决方案分两种场景(XSLT版本不同写法有区别):
1. XSLT 2.0及以上(推荐,写法更简洁直观)
利用XSLT 2.0新增的节点顺序比较运算符<<(表示节点在另一个节点之前),先定位当前busta之后的第一个capo,再只选这个capo之前的dialogo:
<xsl:template match="p[@class='busta']"> <!-- 先拿到当前busta之后的第一个capo节点,如果没有则为空白 --> <xsl:variable name="first-capo-after" select="following-sibling::p[@class='capo'][1]"/> <!-- 选取符合条件的dialogo:在当前busta之后,且在第一个capo之前(如果有capo的话) --> <xsl:apply-templates select="following-sibling::p[@class='dialogo'][ if ($first-capo-after) then . << $first-capo-after else true() ]"/> </xsl:template>
2. XSLT 1.0(兼容旧版本)
因为XSLT 1.0没有节点顺序运算符,我们需要用generate-id和轴来判断节点的位置关系:
<xsl:template match="p[@class='busta']"> <xsl:variable name="current-busta" select="."/> <!-- 只选那些前面没有「在当前busta之后的capo」的dialogo --> <xsl:apply-templates select="following-sibling::p[@class='dialogo'][ not(preceding-sibling::p[@class='capo'][preceding-sibling::p[@class='busta'][generate-id()=generate-id($current-busta)]]) ]"/> </xsl:template>
逻辑说明
不管用哪种写法,核心都是把dialogo的范围限定在「当前busta」和「第一个后续capo」之间:
- 如果后面有capo,就只选capo之前的dialogo;
- 如果后面没有capo,就选所有后续的dialogo。
拿你的示例场景来说,dialogo 6在capo之后,会被这个逻辑排除掉,不会被错误选中。
内容的提问来源于stack exchange,提问作者H725
相关产品推荐
相关产品推荐

