Reputation: 11
I want to sort XML and get first record after sorting.
I have XML as below
<book>
<book>
<auther>bell</auther>
<lastModifiedDateTime>2019-07-22T09:51:48.000</lastModifiedDateTime>
<code>999</code>
<date>2019-07-30T00:00:00.000</date>
</book>
<book>
<auther>bell</auther>
<lastModifiedDateTime>2019-01-01T09:51:48.000</lastModifiedDateTime>
<code>112</code>
<date>2020-01-30T00:00:00.000</date>
</book>
<book>
<auther>apple</auther>
<lastModifiedDateTime>2019-02-02T10:09:40.000</lastModifiedDateTime>
<code>112</code>
<date>2018-07-10T00:00:00.000</date>
</book>
<book>
<auther>google</auther>
<lastModifiedDateTime>2020-01-29T09:51:48.000</lastModifiedDateTime>
<code>999</code>
<date>2019-07-30T00:00:00.000</date>
</book>
</book>
I want to sort xml by sorting code ascending, date ascending and get last record (the greatest lastModifiedDateTime) if there are same "Code" and "date"
This is my expected result
<book>
<book>
<auther>apple</auther>
<lastModifiedDateTime>2019-02-02T10:09:40.000</lastModifiedDateTime>
<code>112</code>
<date>2018-07-10T00:00:00.000</date>
</book>
<book>
<auther>bell</auther>
<lastModifiedDateTime>2019-01-01T09:51:48.000</lastModifiedDateTime>
<code>112</code>
<date>2020-01-30T00:00:00.000</date>
</book>
<book>
<auther>google</auther>
<lastModifiedDateTime>2020-01-29T09:51:48.000</lastModifiedDateTime>
<code>999</code>
<date>2019-07-30T00:00:00.000</date>
</book>
</book>
I tried this code
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="book">
<xsl:copy>
<xsl:for-each select = "book">
<xsl:sort select='code' order="ascending" data-type="number"/>
<xsl:sort select='date' order="ascending" />
<xsl:sort select='lastModifiedDateTime' order="descending" />
<xsl:if test="position()=1">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
but I can get just only one record.
this is actual record.
<book>
<book>
<auther>apple</auther>
<lastModifiedDateTime>2019-02-02T10:09:40.000</lastModifiedDateTime>
<code>112</code>
<date>2018-07-10T00:00:00.000</date>
</book>
</book>
Upvotes: 1
Views: 869
Reputation: 117102
If I understand this correctly (big IF!), you want to group the records by code
and date
, and get the last modified record in each group. Which could be achieved by:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/book">
<xsl:copy>
<xsl:for-each-group select="book" group-by="string-join((code, date), '|')">
<xsl:for-each select="current-group()">
<xsl:sort select='lastModifiedDateTime' order="descending" />
<xsl:if test="position()=1">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
If you want the results sorted by code
and by date
, then sort the groups:
<xsl:template match="/book">
<xsl:copy>
<xsl:for-each-group select="book" group-by="string-join((code, date), '|')">
<xsl:sort select='code' order="ascending" data-type="number"/>
<xsl:sort select='date' order="ascending" />
<xsl:for-each select="current-group()">
<xsl:sort select='lastModifiedDateTime' order="descending" />
<xsl:if test="position()=1">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
Demo: https://xsltfiddle.liberty-development.net/ncnu9B9
Upvotes: 2