You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XSLT中为特定XML元素生成独立序列编号的问题求助

问题:XSLT中为同类型XML元素按父级Item分组生成序列编号

需求说明

需要实现的效果是:每个<Item>节点下的<ZDoc>和<TDoc>各自独立从1开始递增编号,同类型元素在所属Item内连续编号,期望输出如下:

<Item>
    <ZDoc>
        <seq>1</seq>
    </ZDoc>
    <ZDoc>
        <seq>2</seq>
    </ZDoc>
    <TDoc>
        <seq>1</seq>
    </TDoc>
    <TDoc>
        <seq>2</seq>
    </TDoc>
</Item>
<Item>
    <ZDoc>
        <seq>1</seq>
    </ZDoc>
    <ZDoc>
        <seq>2</seq>
    </ZDoc>
    <TDoc>
        <seq>1</seq>
    </TDoc>
    <TDoc>
        <seq>2</seq>
    </TDoc>
</Item>

尝试过的方法及问题

方法一:全局计数模板

编写的模板代码:

<xsl:template name="my_func()">
    <xsl:param name="id_name" select="''"/> 
    <!-- Count elements -->
    <xsl:variable name="seq" select="count(//*[local-name() = $global-id]) + 1"/>
    <!-- Output the generated sequence number -->
    <xsl:value-of select="$seq"/>
</xsl:template>

问题:

  1. 参数名与变量引用不匹配:模板参数是id_name,但变量中用了未定义的$global-id,导致计数逻辑失效;
  2. 使用全局路径//查找元素,会统计整个文档内的同类型元素,而非当前<Item>下的,因此无法实现按Item分组编号,最终输出大量编号1。

方法二:使用position()的模板

编写的模板代码:

<xsl:template name="my_func()">
    <xsl:param name="id" select="()"/>
    <xsl:variable name="auto_number" as="xs:integer" select="position() "/> 
    <xsl:sequence select="xs:integer($auto_number)"/>
</xsl:template>

问题:
position()返回的是当前节点在所有兄弟节点中的位置,而非同类型兄弟的位置。比如<Item>下的节点顺序是ZDoc、ZDoc、TDoc、TDoc,TDoc的position()值为3、4,调用模板时会直接复用这个值,导致TDoc的编号从2/3开始(取决于调用上下文),无法从1重新计数。

解决方案

核心逻辑:针对每个元素,计算它在所属父节点下的同类型兄弟节点中的位置,而非全局或所有兄弟的位置。

方案1:直接使用XPath计算(无需模板)

在匹配ZDoc/TDoc的模板中,直接用XPath计算位置:

<!-- 匹配Item节点,保留结构并处理子节点 -->
<xsl:template match="Item">
  <xsl:copy>
    <xsl:apply-templates select="ZDoc | TDoc"/>
  </xsl:copy>
</xsl:template>

<!-- 匹配ZDoc和TDoc,生成seq编号 -->
<xsl:template match="ZDoc | TDoc">
  <xsl:copy>
    <seq>
      <!-- 统计当前节点之前的同类型兄弟节点数量,加1得到编号 -->
      <xsl:value-of select="count(preceding-sibling::*[local-name() = local-name(current())]) + 1"/>
    </seq>
  </xsl:copy>
</xsl:template>

方案2:复用模板(如果需要通用逻辑)

如果需要将编号逻辑封装为模板复用,可传递当前节点作为参数:

<!-- 通用编号模板 -->
<xsl:template name="get-sequence">
  <xsl:param name="current-node"/>
  <xsl:value-of select="count($current-node/preceding-sibling::*[local-name() = local-name($current-node)]) + 1"/>
</xsl:template>

<!-- 调用模板生成编号 -->
<xsl:template match="ZDoc | TDoc">
  <xsl:copy>
    <seq>
      <xsl:call-template name="get-sequence">
        <xsl:with-param name="current-node" select="."/>
      </xsl:call-template>
    </seq>
  </xsl:copy>
</xsl:template>

内容的提问来源于stack exchange,提问作者RamAlx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 03:30:03