XSLT 1.0实现预订号分组排序并去除重复项求助
XSLT 1.0实现分组编号去重+排序的解决方案
XSLT 1.0没有原生去重函数,解决这类问题最常用的是Muenchian分组法——通过给相同分组编号的节点建立索引,只处理每组的第一个节点,就能实现去重。
适配场景的示例XML片段
<bookings> <booking> <reservationNumber>G1-20240501</reservationNumber> </booking> <booking> <reservationNumber>G5-20240502</reservationNumber> </booking> <booking> <reservationNumber>G5-20240503</reservationNumber> </booking> <booking> <reservationNumber>G8-20240504</reservationNumber> </booking> <booking> <reservationNumber>G16-20240505</reservationNumber> </booking> </bookings>
修改后的XSLT代码(实现去重+排序)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 给每个分组编号建索引,用提取出的数字作为键值 --> <xsl:key name="groupNumKey" match="booking" use="substring-before(substring-after(reservationNumber, 'G'), '-')"/> <xsl:template match="/"> <!-- 只选中每组的第一个节点,过滤重复项 --> <xsl:for-each select="bookings/booking[generate-id() = generate-id(key('groupNumKey', substring-before(substring-after(reservationNumber, 'G'), '-'))[1])]"> <!-- 转成数字排序,避免字符串排序导致16排在5前面的问题 --> <xsl:sort select="number(substring-before(substring-after(reservationNumber, 'G'), '-'))" data-type="number" order="ascending"/> <!-- 输出带点的格式,最后一个节点不加逗号 --> <xsl:value-of select="concat(substring-before(substring-after(reservationNumber, 'G'), '-'), '.')"/> <xsl:if test="position() != last()">, </xsl:if> </xsl:for-each> </xsl:template> </xsl:stylesheet>
关键步骤说明
- 建索引:用
<xsl:key>把所有booking节点按提取出的分组编号归类,相同编号的节点会被分到同一组。 - 去重筛选:
generate-id()函数会给每个节点生成唯一ID,只有每组第一个节点的ID会和索引返回的第一个节点ID一致,以此过滤重复编号。 - 正确排序:把提取的编号转成数字类型再排序,避免字符串排序的bug(比如字符串"16"会被判定为小于"5")。
- 格式控制:通过
position() != last()判断是否添加逗号,保证输出格式整洁。
最终输出
1., 5., 8., 16.
内容的提问来源于stack exchange,提问作者Ella
相关产品推荐
相关产品推荐

