I'm trying to convert XML to XML using XSLT. The output XML should be sorted based on ModificationTime element in the input XML. Below is the xml code.
<?xml version="1.0" encoding="UTF-8"?>
<Process>
<currentDayAndHour>@Fri16</currentDayAndHour>
<!-- Few elements here. Need to retain them -->
<rowCount>1</rowCount>
<currentRow>1</currentRow>
<ClientList>
<Status>0</Status>
<ServerResponse>
<Code>0</Code>
<Text>OK</Text>
</ServerResponse>
<ServiceStartTime>2012-11-09 16:06:42.786</ServiceStartTime>
<ServiceEndTime>2012-11-09 16:06:42.827</ServiceEndTime>
<Files>
<File>
<Name>test.20121107215230411.txt</Name>
<Size>29</Size>
<Type>Regular</Type>
<Permissions>-rw-r--r--</Permissions>
<ModificationTime>1352343152</ModificationTime>
<Owner>19737</Owner>
<Group>70902</Group>
</File>
<File>
<Name>test.20121107183757513.txt</Name>
<Size>29</Size>
<Type>Regular</Type>
<Permissions>-rw-r--r--</Permissions>
<ModificationTime>1352331478</ModificationTime>
<Owner>19737</Owner>
<Group>70902</Group>
</File>
<File>
<Name>test1.20121107215230500.txt</Name>
<Size>32</Size>
<Type>Regular</Type>
<Permissions>-rw-r--r--</Permissions>
<ModificationTime>1352343152</ModificationTime>
<Owner>19737</Owner>
<Group>70902</Group>
</File>
<File>
<Name>test1.txt</Name>
<Size>32</Size>
<Type>Regular</Type>
<Permissions>-rw-r--r--</Permissions>
<ModificationTime>1352323788</ModificationTime>
<Owner>65174</Owner>
<Group>75431</Group>
</File>
<File>
<Name>HMP_test.txt</Name>
<Size>28</Size>
<Type>Regular</Type>
<Permissions>-rw-r--r--</Permissions>
<ModificationTime>1352199478</ModificationTime>
<Owner>19737</Owner>
<Group>70902</Group>
</File>
<File>
<Name>test1.20121107183757585.txt</Name>
<Size>32</Size>
<Type>Regular</Type>
<Permissions>-rw-r--r--</Permissions>
<ModificationTime>1352331478</ModificationTime>
<Owner>19737</Owner>
<Group>70902</Group>
</File>
<File>
<Name>client_access.20121108101411179.txt</Name>
<Size>4182</Size>
<Type>Regular</Type>
<Permissions>-rw-r--r--</Permissions>
<ModificationTime>1352387653</ModificationTime>
<Owner>19737</Owner>
<Group>70902</Group>
</File>
<File>
<Name>TechMtngAgenda.txt</Name>
<Size>107</Size>
<Type>Regular</Type>
<Permissions>-rw-r--r--</Permissions>
<ModificationTime>1352044842</ModificationTime>
<Owner>19737</Owner>
<Group>70902</Group>
</File>
<File>
<Name>test.txt</Name>
<Size>29</Size>
<Type>Regular</Type>
<Permissions>-rw-r--r--</Permissions>
<ModificationTime>1350063313</ModificationTime>
<Owner>19737</Owner>
<Group>70902</Group>
</File>
</Files>
</ClientList>
<currentDocument>1</currentDocument>
</Process>
I need the output XML with all the input elements but Files tag should contain each File in the increasing order of ModificationTime. I'm kindof new to XSLT. I tried using xsl:sort but not able to get desired result.
This stylesheet will do what you want in XSLT 1.0
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Identity template -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Files">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="File">
<xsl:sort order="ascending" data-type="number" select="ModificationTime"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
This stylesheet will do what you want in XSLT 2.0
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<!-- Identity template -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Files">
<xsl:copy>
<xsl:sequence select="@*"/>
<xsl:perform-sort select="File">
<xsl:sort order="ascending" select="xs:integer(ModificationTime)"/>
</xsl:perform-sort>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
In both cases the Identity template is used to copy the document exactly and a single xsl:template is introduced to override the the handling of the Files element. In the XSLT 1.0 example xsl:apply-templates is used with xsl:sort to sort the File elements by ModificationTime. The <xsl:apply-templates select="File"> the handling of the sorted File elements is passed back to the Identity template so it could potentially be overridden further.
In the XSLT 2.0 example xsl:sequence is used to directly insert the input node into the result tree. Likewise xsl:perform-sort returns the sorted sequence directly rather than performing additional instructions to copy the element. Note that these changes will probably make the stylesheet faster to execute but also reduce the flexibility of future maintenance. It's much harder to add overrides when you are selecting things directly. The XSLT 1.0 stylesheet or it's style of handling could be done in XSLT 2.0 without major changes. One final note, both of these examples omit any node() children of Files that is not a File element. To capture those you could add in XSLT 1.0
<xsl:apply-templates select="node()[not(self::File)]"/>
Or in XSLT 2.0 only
<xsl:apply-templates select="node() except File"/>
or
<xsl:sequence select="node() except File"/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With