如何用XSLT处理重复ReplyDTO节点,获取最新estimateNo
Solution to Deduplicate ReplyDTO by estimateNo (Keep Latest by Date/Time)
To solve this problem, we need to group ReplyDTO elements by their estimateNo, then retain only the entry with the most recent creationDate and creationTime for each group. Below are solutions for both XSLT 2.0+ (simpler) and XSLT 1.0 (compatible with older processors).
XSLT 2.0+ Solution
This uses xsl:for-each-group for straightforward grouping, and leverages string concatenation of date/time to find the latest entry (since YYYYMMDDHHMMSS is lexicographically sortable).
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="http://some.url"> <xsl:output method="xml" indent="yes"/> <!-- Identity template: copies all content by default --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- Process the parent element of ReplyDTO --> <xsl:template match="replyelement"> <xsl:copy> <!-- Group ReplyDTO elements by estimateNo --> <xsl:for-each-group select="ns1:ReplyDTO" group-by="ns1:estimateNo"> <!-- Select the entry with the latest creationDate + creationTime --> <xsl:sequence select="current-group()[ concat(ns1:creationDate, ns1:creationTime) = max(current-group()/concat(ns1:creationDate, ns1:creationTime)) ]"/> </xsl:for-each-group> <!-- Copy any non-ReplyDTO child elements from the original --> <xsl:apply-templates select="node()[not(self::ns1:ReplyDTO)]"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
How it works:
- Identity Template: Preserves all elements and attributes except where we explicitly override behavior.
- Grouping:
xsl:for-each-groupclustersReplyDTOelements by theirestimateNovalue. - Select Latest Entry: For each group, we compare the concatenated
creationDate+creationTimestring (e.g.,20160404143000) and select the entry where this string equals the maximum value in the group (which corresponds to the most recent timestamp).
XSLT 1.0 Solution
If you're limited to XSLT 1.0, use Muenchian grouping to group elements, then sort to find the latest entry.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="http://some.url"> <xsl:output method="xml" indent="yes"/> <!-- Key to group ReplyDTO elements by estimateNo --> <xsl:key name="replyByEstimateNo" match="ns1:ReplyDTO" use="ns1:estimateNo"/> <!-- Identity template --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- Process the parent element of ReplyDTO --> <xsl:template match="replyelement"> <xsl:copy> <!-- Iterate over unique estimateNo groups --> <xsl:for-each select="ns1:ReplyDTO[generate-id() = generate-id(key('replyByEstimateNo', ns1:estimateNo)[1])]"> <!-- Get all entries in the current estimateNo group --> <xsl:variable name="currentGroup" select="key('replyByEstimateNo', ns1:estimateNo)"/> <!-- Sort group by concatenated date/time (descending) and pick the first entry --> <xsl:for-each select="$currentGroup"> <xsl:sort select="concat(ns1:creationDate, ns1:creationTime)" order="descending"/> <xsl:if test="position() = 1"> <xsl:copy-of select="."/> </xsl:if> </xsl:for-each> </xsl:for-each> <!-- Copy non-ReplyDTO child elements --> <xsl:apply-templates select="node()[not(self::ns1:ReplyDTO)]"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
How it works:
- Muenchian Grouping: A key is defined to group
ReplyDTOelements byestimateNo. We then select only the first element of each unique group usinggenerate-id. - Sorting: For each group, we sort entries by the concatenated
creationDate+creationTimein descending order, then copy only the first entry (the latest one).
Notes:
- Namespace Handling: Ensure the
ns1namespace in the XSLT matches the one in your input XML. - Time Format: This solution assumes
creationTimeis in a sortable format likeHHMMSS(no colons). If your time includes separators (e.g.,14:30:00), you'll need to normalize it first (e.g., usingtranslate(ns1:creationTime, ':', '')to remove colons). - Ties: If multiple entries in a group have the same latest timestamp, the XSLT 2.0 solution will retain all of them. To keep only one, add
[1]to the end of thexsl:sequenceselect. The XSLT 1.0 solution already keeps only the first sorted entry.
内容的提问来源于stack exchange,提问作者Mazahar Pasha
相关产品推荐
相关产品推荐

