I have xml like below
<Root>
<Element StartDate="2013/12/24"/>
<Element StartDate="2013/12/20"/>
<Element StartDate="2013/12/31"/>
<Element StartDate="2013/12/30"/>
</Root>
How do I get only max date from it using xslt 1.0. Format is YYYY/MM/DD
<Root>
<Element StartDate="2013/12/31"/>
</Root>
CodePudding user response:
YYYY/MM/DD dates will sort correctly (i.e. in chronological order) when the sort order is alphabetical. To get the latest date, you can do simply:
<xsl:template match="/Root">
<latest-date>
<xsl:for-each select="Element">
<xsl:sort select="@StartDate" data-type="text" order="descending" />
<xsl:if test="position()=1">
<xsl:value-of select="@StartDate" />
</xsl:if>
</xsl:for-each>
</latest-date>
</xsl:template>
Note that this is assuming that the format is indeed YYYY/MM/DD - that is with leading zeros for month and day. Your example is ambiguous in this respect.
CodePudding user response:
If it turns out there are day or months numbers without leading zeros (e.g. dates like 2020/8/6
or 2019/5/12
), then you can use multiple xsl:sort
elements to sort the dates first by year, then by month, and then by day, by extracting the 3 different parts of each date, and by telling xsl:sort
to treat the results as numbers (rather than strings) because e.g. 5
comes before 10
numerically, but after it in alphabetical order.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/Root">
<latest-date>
<xsl:for-each select="Element">
<!-- sort by year... -->
<xsl:sort select="substring-before(@StartDate, '/')"
data-type="number" order="descending" />
<!-- ... then by month -->
<xsl:sort select="substring-before(substring-after(@StartDate, '/'), '/')"
data-type="number" order="descending" />
<!-- ... then by day -->
<xsl:sort select="substring-after(substring-after(@StartDate, '/'), '/')"
data-type="number" order="descending" />
<xsl:if test="position()=1">
<xsl:value-of select="@StartDate" />
</xsl:if>
</xsl:for-each>
</latest-date>
</xsl:template>
</xsl:stylesheet>