XSLT转换中line元素拆分后pos属性连续行计数问题求解
解决方案
你的现有代码存在三个核心问题:
- 根模板中定义的
pos变量仅在for-each作用域内生效,没有实际接入输出逻辑 - 拆分生成的
line节点使用的position()是当前父line下子节点的局部位置,无法实现全局计数 - 没有给没有子元素的原生
line节点添加pos属性
你可以通过全局位置计数逻辑实现需求,以下是可用的XSLT 1.0代码:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <!-- 处理没有子元素的原生line节点,添加全局pos属性 --> <xsl:template match="line[not(*)]"> <line> <xsl:attribute name="pos"> <xsl:value-of select="count(preceding-sibling::line[not(*)]) + sum(preceding-sibling::line[*]/count(*)) + 1"/> </xsl:attribute> <xsl:copy-of select="@*"/> </line> </xsl:template> <!-- 有子元素的line节点不需要输出自身,直接处理子元素即可 --> <xsl:template match="line[*]"> <xsl:apply-templates select="*"/> </xsl:template> <!-- 处理line的子元素,生成新的line节点,计算全局pos属性 --> <xsl:template match="line/*"> <line> <xsl:attribute name="pos"> <xsl:value-of select="count(../../preceding-sibling::line[not(*)]) + sum(../../preceding-sibling::line[*]/count(*)) + count(preceding-sibling::*) + 1"/> </xsl:attribute> <xsl:copy-of select="../@* | @*"/> </line> </xsl:template> </xsl:stylesheet>
逻辑说明
计数逻辑由三部分累加得到:
- 前面所有无子元素的line节点数量
- 前面所有有子元素的line节点包含的子节点总数
- 当前节点在所属父line下的位置(仅拆分生成的节点需要计算此项)
三者相加再加1就是最终的全局pos值,完全匹配你给出的输出要求。
内容的提问来源于stack exchange,提问作者XSLT-explorer
相关产品推荐
相关产品推荐

