I have a terrible piece of XML that I need to process through BizTalk, and I have managed to normalise it into this example below. I am no XSLT ninja, but between the web and the VS2010 debugger, I can find my way around XSL.
I now need a clever bit of XSLT to "weed out" the duplicate elements and only keep the latest ones, as decided by the date in the ValidFromDate attribute.
The ValidFromDate attribute is of the XSD:Date type.
<SomeData>
<A ValidFromDate="2011-12-01">A_1</A>
<A ValidFromDate="2012-01-19">A_2</A>
<B CalidFromDate="2011-12-03">B_1</B>
<B ValidFromDate="2012-01-17">B_2</B>
<B ValidFromDate="2012-01-19">B_3</B>
<C ValidFromDate="2012-01-20">C_1</C>
<C ValidFromDate="2011-01-20">C_2</C>
</SomeData>
After a transformation I'd like to only keep these lines:
<SomeData>
<A ValidFromDate="2012-01-19">A_2</A>
<B ValidFromDate="2012-01-19">B_3</B>
<C ValidFromDate="2012-01-20">C_1</C>
</SomeData>
Any clues as to how I put that XSL together? I've emptied the internet trying to look for a solution, and I have tried a lot of clever XSL sorting scripts, but none I felt took me in the right direction.
The following stylesheet produces the correct result without any reliance on the input order:
Output:
Note that the result is slightly different than what you listed as the desired output, because
C_1
is actually the latestC
element (i.e. the input is not already sorted). By relying on an initial sort order (and blindly following the listed expected output) the existing answers are actually incorrect.Explanation:
xsl:key
groups all/SomeData/*
byname()
for-each
selects the first item in each group@ValidFromDate
XLST 2.0 solution without relying on input order.
Based on
@ValidFromDate
order:XSLT:
applied on:
produces:
The optimal solution for this problem with Xslt 1.0 would be to use Muenchian grouping. (Given that the elements are already sorted by the ValidFromDate attribute) the following stylesheet should do the trick:
Here is the result I got when running it against your sample Xml:
Based on Pawel's answer, I made the following modification, which produces the same result:
If they produce the same result every time, I like this because it's a little cleaner.
A slightly simpler and shorter XSLT 1.0 solution than that of @lwburk:
when this transformation is applied on the provided XML document:
the wanted, correct result is produced: