XML处理需求:XSLT按Item1出现次数降序取前N个ID的问题
解决XSLT统计并排序item1 ID出现次数的问题
我来帮你搞定这个需求——咱们需要先统计XML里每个item1的ID出现次数,按次数降序排序后取前N个。下面分两种场景给你具体实现方案:
场景1:使用XSLT 2.0及以上版本(推荐)
XSLT 2.0+原生支持分组功能,实现起来更简洁直观:
示例XML输入
<root> <relation> <item1>ID001</item1> </relation> <relation> <item1>ID002</item1> </relation> <relation> <item1>ID001</item1> </relation> <relation> <item1>ID003</item1> </relation> <relation> <item1>ID001</item1> </relation> <relation> <item1>ID002</item1> </relation> </root>
对应的XSLT代码
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 定义要取的前N个ID,可根据需求修改默认值 --> <xsl:param name="topN" select="2"/> <xsl:template match="/"> <top-ids> <!-- 按item1的ID值分组,同时按出现次数降序排序 --> <xsl:for-each-group select="//relation/item1" group-by="."> <xsl:sort select="count(current-group())" data-type="number" order="descending"/> <!-- 只输出前N个ID --> <xsl:if test="position() <= $topN"> <top-id> <id><xsl:value-of select="current-grouping-key()"/></id> <occurrences><xsl:value-of select="count(current-group())"/></occurrences> </top-id> </xsl:if> </xsl:for-each-group> </top-ids> </xsl:template> </xsl:stylesheet>
代码说明
<xsl:for-each-group>:按item1的文本值分组,current-group()获取当前组的所有节点,count(current-group())就是该ID的出现次数<xsl:sort>:按次数降序排序,data-type="number"确保按数值大小排序,而非字符串<xsl:if test="position() <= $topN">:筛选出排序后的前N个结果
场景2:只能使用XSLT 1.0版本
XSLT 1.0没有原生分组功能,需要用Muenchian分组法实现:
XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl"> <xsl:param name="topN" select="2"/> <!-- 定义分组键,用于Muenchian分组 --> <xsl:key name="item1-key" match="relation/item1" use="."/> <xsl:template match="/"> <!-- 第一步:收集所有唯一ID及其出现次数 --> <xsl:variable name="id-counts"> <xsl:for-each select="//relation/item1[generate-id() = generate-id(key('item1-key', .)[1])]"> <id-count> <id><xsl:value-of select="."/></id> <count><xsl:value-of select="count(key('item1-key', .))"/></count> </id-count> </xsl:for-each> </xsl:variable> <!-- 第二步:将临时节点转为可操作的节点集(依赖EXSLT扩展,多数处理器支持) --> <xsl:variable name="sorted-id-counts" select="exsl:node-set($id-counts)/id-count"/> <!-- 第三步:排序并输出前N个ID --> <top-ids> <xsl:for-each select="$sorted-id-counts"> <xsl:sort select="count" data-type="number" order="descending"/> <xsl:if test="position() <= $topN"> <top-id> <id><xsl:value-of select="id"/></id> <occurrences><xsl:value-of select="count"/></occurrences> </top-id> </xsl:if> </xsl:for-each> </top-ids> </xsl:template> </xsl:stylesheet>
额外提示
- 如果需要忽略ID的大小写,可以在分组时统一转换,比如XSLT 2.0+用
group-by="lower-case(.)" - 可以根据需求调整输出格式,比如只输出纯ID列表,不需要次数字段
内容的提问来源于stack exchange,提问作者itachi737
相关产品推荐
相关产品推荐

