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

如何使用XSLT过滤XML,保留每个用户的最高sequenceNr记录

问题描述

我有一个包含用户信息的XML,每个用户单日可能有多条变更记录,由sequenceNr(序列号)标识。需要过滤后保留每个用户(按ID+startDate分组)对应的最高sequenceNr记录。

原始XML示例:

<userValues>
    <user>
        <ID>1</ID>
        <startDate>20241013</startDate>
        <someValue>200</someValue>
        <sequenceNr>1</sequenceNr>
    </user>
    <user>
        <ID>1</ID>
        <startDate>20241013</startDate>
        <someValue>500</someValue>
        <sequenceNr>2</sequenceNr>
    </user>
    <user>
        <ID>2</ID>
        <startDate>20241001</startDate>
        <someValue>200</someValue>
        <sequenceNr>1</sequenceNr>
    </user>
    <user>
        <ID>3</ID>
        <startDate>20241001</startDate>
        <someValue>200</someValue>
        <sequenceNr>1</sequenceNr>
    </user>
</userValues>

期望过滤结果:

<userValues>
    <user>
        <ID>1</ID>
        <startDate>20241013</startDate>
        <someValue>500</someValue>
        <sequenceNr>2</sequenceNr>
    </user>
    <user>
        <ID>2</ID>
        <startDate>20241001</startDate>
        <someValue>200</someValue>
        <sequenceNr>1</sequenceNr>
    </user>
    <user>
        <ID>3</ID>
        <startDate>20241001</startDate>
        <someValue>200</someValue>
        <sequenceNr>1</sequenceNr>
    </user>
</userValues>

我可以在XSLT处理前将XML按ID、startDate和sequenceNr排序,刚接触XSLT,想了解该需求是否可实现及具体方法。

实现方案

这个需求完全可以用XSLT实现,下面提供两种适配不同场景的方法:

方法一:利用预排序后的XML直接取每组最后一条

既然你可以提前将XML按ID→startDate→sequenceNr升序排序,那每组(相同ID+startDate)的最高sequenceNr记录就是该组的最后一条。用XSLT的分组逻辑可以轻松提取:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <!-- 定义分组键:ID+startDate的组合,避免不同ID/日期的组合冲突 -->
    <xsl:key name="userGroup" match="user" use="concat(ID, '|', startDate)"/>

    <xsl:template match="/userValues">
        <userValues>
            <!-- 筛选出每组的最后一条记录 -->
            <xsl:for-each select="user[generate-id() = generate-id(key('userGroup', concat(ID, '|', startDate))[last()])]">
                <xsl:copy-of select="."/>
            </xsl:for-each>
        </userValues>
    </xsl:template>
</xsl:stylesheet>

原理:通过concat(ID, '|', startDate)生成唯一分组键,用key()获取同组所有记录,取[last()]就是排序后的最高序列号记录,再用generate-id()匹配筛选出这些记录。

方法二:无需预排序,直接分组找最大sequenceNr

如果不想提前排序,也可以直接在XSLT中计算每组的最大sequenceNr,再筛选对应记录:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <xsl:key name="userGroup" match="user" use="concat(ID, '|', startDate)"/>

    <xsl:template match="/userValues">
        <userValues>
            <!-- 遍历每个唯一分组 -->
            <xsl:for-each select="user[generate-id() = generate-id(key('userGroup', concat(ID, '|', startDate))[1])]">
                <!-- 获取当前分组的最大sequenceNr值 -->
                <xsl:variable name="maxSeq" select="max(key('userGroup', concat(ID, '|', startDate))/sequenceNr)"/>
                <!-- 复制对应最大序列号的记录 -->
                <xsl:copy-of select="key('userGroup', concat(ID, '|', startDate))[sequenceNr = $maxSeq]"/>
            </xsl:for-each>
        </userValues>
    </xsl:template>
</xsl:stylesheet>

原理:同样用分组键分组,对每个分组计算max(sequenceNr),再筛选出该组中sequenceNr等于最大值的记录。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 06:45:18