You need to enable JavaScript to run this app. XSLT嵌套排序实现XML p节点按文本及number元素数值排序咨询
优惠活动
大模型
产品
解决方案
定价
更多

XSLT嵌套排序实现XML p节点按文本及number元素数值排序咨询

问题原因

你编写的代码存在两处核心逻辑错误:

  1. 排序嵌套逻辑无效:<xsl:for-each select=".//p">已经将节点集遍历到单个p元素,此时在内部对单个节点调用<xsl:apply-templates>时加排序规则没有任何作用,排序仅对节点集合生效。
  2. 未兼容无number的标题节点:同分组下的标题p节点没有number子元素,需要保证这类节点排在同分组的最前面。

正确实现方案

以下提供XSLT 1.0兼容版本的实现,可直接运行得到预期结果:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
    
    <!-- 匹配livre根节点,输出新的livre容器 -->
    <xsl:template match="livre">
        <livre>
            <!-- 对所有p节点按优先级排序 -->
            <xsl:apply-templates select="p">
                <!-- 第一优先级:按第一个number前的文本前缀字典序排序 -->
                <xsl:sort select="substring-before(., string(number[1]))" data-type="text" order="ascending"/>
                <!-- 第二优先级:按第一个number的数值升序排序,无number的节点值为空默认排最前 -->
                <xsl:sort select="number[1]" data-type="number" order="ascending"/>
                <!-- 第三优先级:按第二个number的数值升序排序 -->
                <xsl:sort select="number[2]" data-type="number" order="ascending"/>
            </xsl:apply-templates>
        </livre>
    </xsl:template>
    
    <!-- 原样复制p节点及其全部子内容 -->
    <xsl:template match="p">
        <xsl:copy-of select="."/>
    </xsl:template>
</xsl:stylesheet>

如果使用XSLT 2.0及以上版本,可以显式处理空值逻辑,可读性更强:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
    
    <xsl:template match="livre">
        <livre>
            <xsl:apply-templates select="p">
                <xsl:sort select="if (exists(number[1])) then substring-before(., string(number[1])) else normalize-space(substring-before(., ')')) || ')'" data-type="text" order="ascending"/>
                <xsl:sort select="if (exists(number[1])) then number(number[1]) else 0" data-type="number" order="ascending"/>
                <xsl:sort select="if (exists(number[2])) then number(number[2]) else 0" data-type="number" order="ascending"/>
            </xsl:apply-templates>
        </livre>
    </xsl:template>
    
    <xsl:template match="p">
        <xsl:copy-of select="."/>
    </xsl:template>
</xsl:stylesheet>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 11:03:03