使用XSLT提取各用户的最大LastModified日期(去重用户ID)
解决XML按用户提取最新LastModified日期的XSLT方案
核心思路是按<User>字段分组,每组内筛选出<LastModified>日期最大的记录,确保输出的用户ID不重复。以下分XSLT版本给出具体实现:
示例XML数据
假设你的XML结构如下(方便对照代码理解):
<Records> <Record> <User>5</User> <LastModified>10/3/2023</LastModified> <!-- 其他字段 --> </Record> <Record> <User>5</User> <LastModified>15/3/2023</LastModified> <!-- 其他字段 --> </Record> <Record> <User>3</User> <LastModified>20/2/2023</LastModified> <!-- 其他字段 --> </Record> </Records>
XSLT 1.0 实现(Muenchian分组法)
XSLT 1.0没有原生分组功能,用Muenchian分组先聚合同用户的记录,再筛选最新日期:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 定义键,按<User>值分组 --> <xsl:key name="userGroups" match="Record" use="User"/> <xsl:template match="/"> <LatestRecords> <!-- 只处理每个用户组的首个节点(确保用户唯一) --> <xsl:for-each select="Records/Record[generate-id() = generate-id(key('userGroups', User)[1])]"> <xsl:variable name="currentUser" select="User"/> <!-- 当前用户组内按日期降序排序 --> <xsl:for-each select="key('userGroups', $currentUser)"> <!-- 把日期的/去掉转成数字,避免字符串排序误差 --> <xsl:sort select="translate(LastModified, '/', '')" data-type="number" order="descending"/> <!-- 取排序后的第一条(即最新日期的记录) --> <xsl:if test="position() = 1"> <Record> <User><xsl:value-of select="User"/></User> <LastModified><xsl:value-of select="LastModified"/></LastModified> <!-- 需要保留其他字段的话,在这里添加对应节点和value-of --> </Record> </xsl:if> </xsl:for-each> </xsl:for-each> </LatestRecords> </xsl:template> </xsl:stylesheet>
XSLT 2.0+ 实现(原生分组)
XSLT 2.0及以上支持group-by语法,代码更简洁:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <LatestRecords> <!-- 按<User>分组 --> <xsl:for-each-group select="Records/Record" group-by="User"> <!-- 组内筛选出LastModified最大的记录 --> <xsl:variable name="latestRecord" select=" current-group()[ translate(LastModified, '/', '') = max(current-group()/translate(LastModified, '/', '')) ] "/> <Record> <User><xsl:value-of select="$latestRecord/User"/></User> <LastModified><xsl:value-of select="$latestRecord/LastModified"/></LastModified> <!-- 其他字段按需添加 --> </Record> </xsl:for-each-group> </LatestRecords> </xsl:template> </xsl:stylesheet>
关键注意点
- 日期排序准确性:因为你的日期格式是
日/月/年,直接字符串排序会出错(比如15/3/2023和10/4/2023),所以用translate(LastModified, '/', '')把日期转成纯数字(如15032023),再按数字排序或取最大值。如果是ISO标准格式YYYY-MM-DD,可以直接用字符串比较。 - 保留其他字段:如果需要输出原记录的其他字段,直接在输出的
<Record>节点内添加对应的<xsl:value-of select="字段名"/>即可。
内容的提问来源于stack exchange,提问作者Ryzix
相关产品推荐
相关产品推荐

