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

XSLT实现文档中任意位置<note>元素的连续编号问题

解决XSLT中嵌套元素的全局连续编号问题

核心思路

要实现文档顺序的连续编号,关键是准确统计当前<note>节点之前所有已出现的<note>节点总数,再加1得到当前编号。无需分段统计,直接通过XPath轴或<xsl:number>实现全局计数即可。

示例输入XML

<doc>
  <p>第一段文本<note>注释1</note>,包含<q>引用内容<note>注释2</note></q>,继续文本<note>注释3</note></p>
  <p>第二段文本<note>注释4</note></p>
</doc>

具体实现方案

方案1:XSLT 2.0+ 简洁写法

利用XPath 2.0的文档顺序比较运算符<<,直接统计所有在当前节点之前的<note>:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!-- 处理正文,生成注释引用 -->
  <xsl:template match="note">
    <sup>
      <xsl:variable name="note-num" select="count(//note[. << current()]) + 1"/>
      <a href="#note-{$note-num}" id="ref-{$note-num}">
        [<xsl:value-of select="$note-num"/>]
      </a>
    </sup>
  </xsl:template>

  <!-- 保留原文本结构(如<p>、<q>) -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- 生成页面末尾的注释块 -->
  <xsl:template match="/">
    <html>
      <body>
        <xsl:apply-templates/>
        <div class="notes">
          <h3>注释</h3>
          <ol>
            <xsl:apply-templates select="//note" mode="note-block"/>
          </ol>
        </div>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="note" mode="note-block">
    <xsl:variable name="note-num" select="count(//note[. << current()]) + 1"/>
    <li id="note-{$note-num}">
      <xsl:value-of select="."/>
      <a href="#ref-{$note-num}">↑</a>
    </li>
  </xsl:template>
</xsl:stylesheet>

方案2:兼容XSLT 1.0的写法

XSLT 1.0不支持<<,可以用generate-id()比较节点唯一性(先出现的节点ID更小):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="note">
    <sup>
      <xsl:variable name="note-num" select="count(/descendant::note[generate-id(.) < generate-id(current())]) + 1"/>
      <a href="#note-{$note-num}" id="ref-{$note-num}">
        [<xsl:value-of select="$note-num"/>]
      </a>
    </sup>
  </xsl:template>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/">
    <html>
      <body>
        <xsl:apply-templates/>
        <div class="notes">
          <h3>注释</h3>
          <ol>
            <xsl:apply-templates select="//note" mode="note-block"/>
          </ol>
        </div>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="note" mode="note-block">
    <xsl:variable name="note-num" select="count(/descendant::note[generate-id(.) < generate-id(current())]) + 1"/>
    <li id="note-{$note-num}">
      <xsl:value-of select="."/>
      <a href="#ref-{$note-num}">↑</a>
    </li>
  </xsl:template>
</xsl:stylesheet>

方案3:XSLT 2.0+ 高性能写法

用<xsl:number>的level="any"属性,直接按文档顺序统计所有层级的<note>,性能优于全局count():

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="note">
    <sup>
      <xsl:variable name="note-num">
        <xsl:number level="any" count="note"/>
      </xsl:variable>
      <a href="#note-{$note-num}" id="ref-{$note-num}">
        [<xsl:value-of select="$note-num"/>]
      </a>
    </sup>
  </xsl:template>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/">
    <html>
      <body>
        <xsl:apply-templates/>
        <div class="notes">
          <h3>注释</h3>
          <ol>
            <xsl:apply-templates select="//note" mode="note-block"/>
          </ol>
        </div>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="note" mode="note-block">
    <xsl:variable name="note-num">
      <xsl:number level="any" count="note"/>
    </xsl:variable>
    <li id="note-{$note-num}">
      <xsl:value-of select="."/>
      <a href="#ref-{$note-num}">↑</a>
    </li>
  </xsl:template>
</xsl:stylesheet>

问题根源说明

之前的代码编号重置,是因为只统计了当前<p>之前的<note>,没有包含当前<p>内、当前<note>之前的嵌套<note>。上述方案通过全局统计文档顺序在前的所有<note>,不管节点层级,自然解决了重置问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 20:11:09