如何使用XSL按字母顺序排序名称并同步对应引用ID?
XSL解决方案:按名称排序并同步引用ID
以下是实现需求的XSLT 2.0解决方案,可将<cross-refs>元素内的名称按字母顺序排序,同时同步更新对应的refid属性值:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <!-- 处理cross-refs元素 --> <xsl:template match="cross-refs"> <xsl:copy> <!-- 保留原id属性 --> <xsl:copy-of select="@id"/> <!-- 拆分名称列表与引用ID列表 --> <xsl:variable name="names" select="tokenize(normalize-space(.), '; ')"/> <xsl:variable name="refids" select="tokenize(@refid, ' ')"/> <!-- 生成名称与ID的配对节点 --> <xsl:variable name="paired"> <xsl:for-each select="1 to count($names)"> <pair> <name><xsl:value-of select="$names[current()]"/></name> <refid><xsl:value-of select="$refids[current()]"/></refid> </pair> </xsl:for-each> </xsl:variable> <!-- 按名称字母顺序排序(大小写不敏感) --> <xsl:variable name="sorted-pairs" select="$paired/pair/upper-case(name) => sort() => for-each(.)/.."/> <!-- 构建新的refid属性 --> <xsl:attribute name="refid"> <xsl:value-of select="$sorted-pairs/refid" separator=" "/> </xsl:attribute> <!-- 构建排序后的名称文本 --> <xsl:value-of select="$sorted-pairs/name" separator="; "/> </xsl:copy> </xsl:template> <!-- 默认模板:原样复制其他节点 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
关键步骤说明
- 拆分与配对:通过
tokenize函数将名称文本和refid属性拆分为数组,再通过循环将位置对应的名称与ID绑定为<pair>节点,确保关联关系不丢失。 - 大小写不敏感排序:使用
upper-case统一名称的大小写后排序,避免因大小写差异导致排序错误(如King和king会被视为同一顺序层级)。 - 重新拼接:将排序后的ID用空格拼接成新的
refid属性值,名称用;拼接成新的文本内容,最终生成符合要求的<cross-refs>元素。
测试验证
针对你提供的输入:
<cross-refs id="c0065" refid="b0110 b0190 b0035">Loyal 2018; Anbu 1983; King 2022</cross-refs>
经过上述XSLT处理后,输出结果为:
<cross-refs id="c0065" refid="b0190 b0035 b0110">Anbu 1983; King 2022; Loyal 2018</cross-refs>
内容的提问来源于stack exchange,提问作者Mahesh M
相关产品推荐
相关产品推荐

