如何用XSLT为XML文档中所有<note>元素按全局位置编号
解决XML中元素全局顺序编号的XSLT方案
问题分析
你之前的XSLT代码出现所有position()函数——它仅返回当前节点在父节点子列表中的位置,而非整个文档中
正确实现方案
下面提供两种可靠的全局编号实现方式,均能按rank属性。
示例XML结构
假设你的XML结构如下:
<root> <section> <note>第一个注释</note> <para>段落内容<note>第二个注释</note></para> </section> <note>第三个注释</note> </root>
方案一:使用<xsl:number>全局计数
利用<xsl:number>的level="any"属性,直接统计整个文档中所有
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 默认模板:复制所有非note节点和属性 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 专门处理note元素 --> <xsl:template match="note"> <note> <!-- 添加rank属性:note+全局编号 --> <xsl:attribute name="rank"> <xsl:text>note</xsl:text> <xsl:number level="any" count="note"/> </xsl:attribute> <!-- 内容前添加"数字. "前缀 --> <xsl:number level="any" count="note"/>. <xsl:apply-templates/> </note> </xsl:template> </xsl:stylesheet>
说明:level="any"会忽略节点层级,遍历整个文档统计匹配count="note"的元素,直接得到全局递增的编号。
方案二:使用<xsl:key>和节点顺序比较
通过键收集所有<<计算当前节点的全局位置:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 定义键:匹配所有note元素 --> <xsl:key name="all-notes" match="note" use="true()"/> <!-- 默认模板:复制所有非note节点和属性 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 处理note元素 --> <xsl:template match="note"> <!-- 计算当前note的全局索引 --> <xsl:variable name="note-index" select="count(key('all-notes', true())[. << current()]) + 1"/> <!-- 生成带rank属性的note节点,添加前缀内容 --> <note rank="note{$note-index}"> <xsl:value-of select="$note-index"/>. <xsl:apply-templates/> </note> </xsl:template> </xsl:stylesheet>
说明:key('all-notes', true())会返回所有[. << current()]筛选出当前节点之前的所有
输出效果
两种方案处理后的XML输出均为:
<root> <section> <note rank="note1">1. 第一个注释</note> <para>段落内容<note rank="note2">2. 第二个注释</note></para> </section> <note rank="note3">3. 第三个注释</note> </root>
内容的提问来源于stack exchange,提问作者fauve
相关产品推荐
相关产品推荐

