XSLT 2.0按值和元素分组XML节点并处理特定节点值问题
XSLT 2.0转换需求:分组去重+特定节点值优先级处理
需求概述
- 按
applicationId对<Application>节点进行分组 - 分组后按子元素名称去重,每个元素仅保留一个实例
- 针对
<cust_overallduedilligencestatus>节点,若同一applicationId分组内存在id为197280的项,最终保留该值;无此值则保留原有内容
输入XML
<?xml version='1.0' encoding='UTF-8'?> <Applications> <Application> <applicationId>280</applicationId> <cust_IDCheckIDCollation> <Option> <id>197249</id> </Option> </cust_IDCheckIDCollation> <cust_overallduedilligencestatus> <Option> <id>197276</id> </Option> </cust_overallduedilligencestatus> </Application> <Application> <applicationId>292</applicationId> <cust_IDCheckIDCollation> <Option> <id>197249</id> </Option> </cust_IDCheckIDCollation> <cust_overallduedilligencestatus> <Option> <id>197276</id> </Option> </cust_overallduedilligencestatus> </Application> <Application> <applicationId>280</applicationId> <cust_OnlineReferenceCheck> <Option> <id>197249</id> </Option> </cust_OnlineReferenceCheck> <cust_overallduedilligencestatus> <Option> <id>197276</id> </Option> </cust_overallduedilligencestatus> </Application> <Application> <applicationId>292</applicationId> <cust_OnlineReferenceCheck> <Option> <id>197249</id> </Option> </cust_OnlineReferenceCheck> <cust_overallduedilligencestatus> <Option> <id>197276</id> </Option> </cust_overallduedilligencestatus> </Application> <Application> <applicationId>280</applicationId> <cust_AustralianWorkRights> <Option> <id>197250</id> </Option> </cust_AustralianWorkRights> <cust_overallduedilligencestatus> <Option> <id>197276</id> </Option> </cust_overallduedilligencestatus> </Application> <Application> <applicationId>292</applicationId> <cust_AustralianWorkRights> <Option> <id>197250</id> </Option> </cust_AustralianWorkRights> <cust_overallduedilligencestatus> <Option> <id>197276</id> </Option> </cust_overallduedilligencestatus> </Application> <Application> <applicationId>280</applicationId> <cust_NationalPoliceCheck> <Option> <id>197249</id> </Option> </cust_NationalPoliceCheck> <cust_overallduedilligencestatus> <Option> <id>197280</id> </Option> </cust_overallduedilligencestatus> </Application> <Application> <applicationId>292</applicationId> <cust_NationalPoliceCheck> <Option> <id>197249</id> </Option> </cust_NationalPoliceCheck> <cust_overallduedilligencestatus> <Option> <id>197276</id> </Option> </cust_overallduedilligencestatus> </Application> </Applications>
期望输出XML
<Applications> <Application> <applicationId>280</applicationId> <cust_IDCheckIDCollation> <Option> <id>197249</id> </Option> </cust_IDCheckIDCollation> <cust_overallduedilligencestatus> <Option> <id>197280</id> </Option> </cust_overallduedilligencestatus> <cust_OnlineReferenceCheck> <Option> <id>197249</id> </Option> </cust_OnlineReferenceCheck> <cust_AustralianWorkRights> <Option> <id>197250</id> </Option> </cust_AustralianWorkRights> <cust_NationalPoliceCheck> <Option> <id>197249</id> </Option> </cust_NationalPoliceCheck> </Application> <Application> <applicationId>292</applicationId> <cust_IDCheckIDCollation> <Option> <id>197249</id> </Option> </cust_IDCheckIDCollation> <cust_overallduedilligencestatus> <Option> <id>197280</id> </Option> </cust_overallduedilligencestatus> <cust_OnlineReferenceCheck> <Option> <id>197249</id> </Option> </cust_OnlineReferenceCheck> <cust_AustralianWorkRights> <Option> <id>197250</id> </Option> </cust_AustralianWorkRights> <cust_NationalPoliceCheck> <Option> <id>197249</id> </Option> </cust_NationalPoliceCheck> </Application> </Applications>
现有XSLT代码(仅实现分组去重)
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/Applications"> <xsl:copy> <xsl:for-each-group select="Application" group-by="applicationId"> <xsl:copy> <xsl:copy-of select="applicationId"/> <xsl:for-each-group select="current-group()/(* except applicationId)" group-by="name()"> <xsl:copy-of select="current-group()[1]"/> </xsl:for-each-group> </xsl:copy> </xsl:for-each-group> </xsl:copy> </xsl:template> </xsl:stylesheet>
解决方案:修改后的XSLT代码
核心思路:在子元素分组时,对<cust_overallduedilligencestatus>节点单独判断,优先保留id=197280的项,其他元素按原有逻辑取第一个实例。
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/Applications"> <xsl:copy> <!-- 按applicationId分组 --> <xsl:for-each-group select="Application" group-by="applicationId"> <xsl:copy> <xsl:copy-of select="applicationId"/> <!-- 按子元素名称分组去重 --> <xsl:for-each-group select="current-group()/(* except applicationId)" group-by="name()"> <xsl:choose> <!-- 处理cust_overallduedilligencestatus节点 --> <xsl:when test="current-grouping-key() = 'cust_overallduedilligencestatus'"> <!-- 优先选取id=197280的项,不存在则取第一个 --> <xsl:copy-of select="current-group()[Option/id = '197280'] | current-group()[not(current-group()[Option/id = '197280'])][1]"/> </xsl:when> <!-- 其他元素直接取第一个 --> <xsl:otherwise> <xsl:copy-of select="current-group()[1]"/> </xsl:otherwise> </xsl:choose> </xsl:for-each-group> </xsl:copy> </xsl:for-each-group> </xsl:copy> </xsl:template> </xsl:stylesheet>
关键逻辑说明
- 使用
current-grouping-key()判断当前分组的元素名称是否为cust_overallduedilligencestatus - 用
current-group()[Option/id = '197280']筛选出该分组内id为197280的节点,若存在则保留;若不存在则通过current-group()[not(...)][1]取第一个节点 - 其他元素保持原有去重逻辑,取分组内第一个实例
内容的提问来源于stack exchange,提问作者Madhu N G
相关产品推荐
相关产品推荐

