如何在XSL 1.0中跨thead和tbody获取行索引?
解决XSLT 1.0中跨Thead和Tbody的全局行索引问题
我明白你的痛点:原来的模板只能统计当前Entry所在区块(Thead或Tbody)内的行号,没法把Thead里的行也算进全局索引里。要实现跨区块的行号统计,我们需要把整个Tgroup下的所有Row都纳入计算范围,而不是局限于当前Entry的直接祖先节点。
核心思路
每个Entry的全局行号 = 当前Tgroup中所有在当前Row之前的Row数量 + 1。这里的"之前"包括Thead里的所有前置Row,以及当前区块(Tbody/Thead)里的前置Row。
改进后的模板代码
考虑到你提到原代码用变量存储节点名称(比如name()='Row'),我给出兼容这种写法的版本:
<xsl:template match="Entry"> <!-- 先获取当前Entry所在的Row节点 --> <xsl:variable name="current-row" select="../.." /> <!-- 统计当前Tgroup下,所有在当前Row之前的、名称为Row的节点数量 --> <xsl:variable name="preceding-rows-count" select="count($current-row/ancestor::Tgroup//*[name()='Row'][. << $current-row])" /> <!-- 全局行号 = 前置行数 + 1 --> <xsl:value-of select="$preceding-rows-count + 1" /> </xsl:template>
如果你不需要兼容变量节点名的写法,也可以简化成更直观的版本:
<xsl:template match="Entry"> <xsl:variable name="current-row" select="../.." /> <xsl:value-of select="count($current-row/ancestor::Tgroup//Row[. << $current-row]) + 1" /> </xsl:template>
为什么原来的模板不行?
原来的代码count="../../*[name()='Row']"是统计当前Entry的祖父节点(也就是<Thead>或<Tbody>)下的Row,相当于只统计当前区块内的行,自然没法把Thead的行和Tbody的行连起来计算。而新代码通过ancestor::Tgroup//*[name()='Row']锁定了整个表格组内的所有Row,再用<<运算符筛选出在当前Row之前的节点,这样就能准确得到全局的行位置了。
测试验证
用你提供的示例XML测试:
- Thead里的Entry行号为1
- Tbody第一个Row的Entry行号为2
- Tbody第二个Row的Entry行号为3
完全符合跨区块统计行索引的需求。
内容的提问来源于stack exchange,提问作者dube
相关产品推荐
相关产品推荐

