XSLT处理重复RetrieveReplyDTO节点:获取最新estimateNo
处理重复estimateNo并保留最新RetrieveReplyDTO节点的解决方案
首先明确咱们的核心需求:从XML的RetrieveReplyDTO节点中,对重复的estimateNo进行去重,只保留对应creationDate和creationTime最新的那条数据。下面我分享两种实用的实现方案:
方案一:使用XSLT 2.0处理(适合纯XML场景)
XSLT是处理XML数据转换的利器,用它可以直接在XML层面完成分组、排序和筛选:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns0="some.url"> <xsl:output method="xml" indent="yes" encoding="UTF-8"/> <!-- 匹配根节点,保留原XML结构 --> <xsl:template match="/ns0:retrieveResponse"> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:apply-templates select="ns0:out"/> </xsl:copy> </xsl:template> <!-- 处理out节点,对RetrieveReplyDTO按estimateNo分组 --> <xsl:template match="ns0:out"> <xsl:copy> <xsl:for-each-group select="ns0:replyE/ns0:RetrieveReplyDTO" group-by="ns0:estimateNo"> <!-- 每组内按creationDate+creationTime降序排序,取第一条(最新的) --> <xsl:sort select="concat(ns0:creationDate, 'T', ns0:creationTime)" order="descending" data-type="text"/> <xsl:copy-of select="current-group()[1]"/> </xsl:for-each-group> </xsl:copy> </xsl:template> <!-- 保留其他节点的默认复制逻辑 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
代码说明:
- 用
<xsl:for-each-group>按estimateNo对RetrieveReplyDTO节点分组,把相同编号的节点归为一组 - 把
creationDate和creationTime拼接成标准的日期时间字符串(比如20240520T143000),按这个字符串降序排序,确保最新的条目排在每组最前面 - 取每组的第一个节点,就是我们需要保留的最新数据
方案二:使用Java代码处理(适合业务系统集成场景)
如果你的需求是在Java应用中处理这个XML,可以先把XML解析成Java对象,再通过分组筛选实现:
步骤1:定义RetrieveReplyDTO实体类(用JAXB注解映射XML)
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @XmlRootElement(name = "RetrieveReplyDTO", namespace = "some.url") public class RetrieveReplyDTO { @XmlElement(namespace = "some.url") private String estimateNo; @XmlElement(namespace = "some.url") private String creationDate; // 格式示例:yyyyMMdd @XmlElement(namespace = "some.url") private String creationTime; // 格式示例:HHmmss // 生成可用于比较的完整日期时间对象 public LocalDateTime getFullCreationDateTime() { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); return LocalDateTime.parse(creationDate + creationTime, formatter); } // 省略getter、setter方法 }
步骤2:解析XML并筛选最新数据
import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; import java.io.File; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class XmlProcessor { public static void main(String[] args) throws Exception { // 解析XML到Java对象 JAXBContext context = JAXBContext.newInstance(RetrieveResponse.class); Unmarshaller unmarshaller = context.createUnmarshaller(); RetrieveResponse response = (RetrieveResponse) unmarshaller.unmarshal(new File("input.xml")); List<RetrieveReplyDTO> dtoList = response.getOut().getReplyE().getRetrieveReplyDTOList(); // 按estimateNo分组,每组保留最新的条目 Map<String, RetrieveReplyDTO> latestDtoMap = dtoList.stream() .collect(Collectors.toMap( RetrieveReplyDTO::getEstimateNo, dto -> dto, (existingDto, newDto) -> { // 比较两个条目的创建时间,保留最新的 return existingDto.getFullCreationDateTime().isAfter(newDto.getFullCreationDateTime()) ? existingDto : newDto; } )); // 转换为列表,得到去重后的最终结果 List<RetrieveReplyDTO> resultList = latestDtoMap.values().stream().collect(Collectors.toList()); // 后续可将resultList写回XML或用于业务逻辑处理 } }
代码说明:
- 用JAXB完成XML到Java对象的映射,方便后续业务操作
- 利用Stream API的
Collectors.toMap方法对estimateNo分组,当遇到重复编号时,通过日期时间比较保留最新的条目 - 最终
resultList就是去重后只保留每个estimateNo最新条目的数据集
内容的提问来源于stack exchange,提问作者Shaik Pasha
相关产品推荐
相关产品推荐

