<cffunction
name="XmlSort"
access="public"
returntype="string"
output="true"
hint="I sort part of an XML documument based on the given XPath and sort characteristics.">
<cfargument
name="Xml"
type="any"
required="true"
hint="I am an XML string or ColdFusion XML document."
/>
<cfargument
name="ParentXPath"
type="string"
required="true"
hint="I am the XPath to the PARENT node of the nodes which are targeted for sorting." />
<cfargument
name="SortXPath"
type="any"
required="false"
default="text()"
hint="I am the XPath value upon which the sort is being conducted. This can be a string or an array (if multiple sorting options are required)."
/>
<cfargument
name="Direction"
type="string"
required="false"
default="ascending"
hint="I am the sort direction."
/>
<cfargument
name="DataType"
type="string"
required="false"
default="text"
hint="I am the type of data that is being used in the sort (to help sorting)."
/>
<cfset var LOCAL = {} />
<cfif IsSimpleValue( ARGUMENTS.SortXPath )>
<cfset LOCAL.SortCopy = ARGUMENTS.SortXPath />
<cfset ARGUMENTS.SortXPath = [ LOCAL.SortCopy ] />
</cfif>
<cfxml variable="LOCAL.Transform">
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:transform
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="#ARGUMENTS.ParentXPath#">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:for-each select="*">
<cfloop
index="LOCAL.SortXPath"
array="#ARGUMENTS.SortXPath#">
<xsl:sort
select="#LOCAL.SortXPath#"
data-type="text"
order="#ARGUMENTS.Direction#"
/>
</cfloop>
<xsl:copy-of select="." />
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:transform>
</cfxml>
<cfreturn XmlTransform(
ARGUMENTS.Xml,
LOCAL.Transform
) />
</cffunction>