Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p><strong>Here is a generic, simple and not long (60 well-formatted lines) solution</strong>.</p> <p><strong>Sorting is performed on</strong> <em>all</em> <strong>wanted attributes and this doesn't require any manual duplication of templates</strong>:</p> <pre><code>&lt;xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:my="my:my" exclude-result-prefixes="my"&gt; &lt;xsl:output omit-xml-declaration="yes" indent="yes"/&gt; &lt;xsl:param name="pSortTypes" as="element()*"&gt; &lt;attr name="name" type="alpha" maxLength="15"/&gt; &lt;attr name="row" type="numeric" maxLength="6"/&gt; &lt;attr name="col" type="numeric" maxLength="4"/&gt; &lt;attr name="tabindex" type="numeric" maxLength="2"/&gt; &lt;attr name="sequence" type="numeric" maxLength="3"/&gt; &lt;/xsl:param&gt; &lt;xsl:template match="*"&gt; &lt;xsl:copy&gt; &lt;xsl:copy-of select="@*"/&gt; &lt;xsl:apply-templates select="*"&gt; &lt;xsl:sort select="my:OrderedAttributeTuple(.)"/&gt; &lt;/xsl:apply-templates&gt; &lt;/xsl:copy&gt; &lt;/xsl:template&gt; &lt;xsl:function name="my:OrderedAttributeTuple" as="xs:string"&gt; &lt;xsl:param name="pElem" as="element()"/&gt; &lt;xsl:variable name="vResult" as="xs:string*"&gt; &lt;xsl:apply-templates select="$pSortTypes"&gt; &lt;xsl:with-param name="pElem" select="$pElem"/&gt; &lt;/xsl:apply-templates&gt; &lt;/xsl:variable&gt; &lt;xsl:sequence select="string-join($vResult, '')"/&gt; &lt;/xsl:function&gt; &lt;xsl:template match="attr"&gt; &lt;xsl:param name="pElem" as="element()"/&gt; &lt;xsl:variable name="vVal" select= "string($pElem/@*[name() eq current()/@name])"/&gt; &lt;xsl:variable name="vPad" as="xs:string*" select= "for $cnt in xs:integer(@maxLength) - string-length($vVal), $i in 1 to $cnt return '.' "/&gt; &lt;xsl:variable name="vPadding" select="string-join($vPad, '')"/&gt; &lt;xsl:variable name="vTuple"&gt; &lt;xsl:sequence select= "if(@type eq 'alpha') then concat($vVal, $vPadding) else concat($vPadding, $vVal) "/&gt; &lt;/xsl:variable&gt; &lt;xsl:sequence select="string($vTuple)"/&gt; &lt;/xsl:template&gt; &lt;/xsl:stylesheet&gt; </code></pre> <p><strong>When this transformation is applied on this XML document</strong>:</p> <pre><code>&lt;items&gt; &lt;item row="5" col="9"/&gt; &lt;item name="d" row="20" col="12" tabindex="" sequence=""/&gt; &lt;item row="1" col="5" /&gt; &lt;item name="d" row="5" col="6" /&gt; &lt;item name="a" row="7" col="8" /&gt; &lt;item name="s" row="1" col="5" tabindex="3" sequence="4"/&gt; &lt;item name="s" row="3" col="3" tabindex="3" sequence="4"/&gt; &lt;item name="c" row="5" col="9"/&gt; &lt;item row="2" col="5" /&gt; &lt;item row="20" col="9"/&gt; &lt;item row="0" col="9"/&gt; &lt;item name="s" row="3" col="3" tabindex="1" sequence="2"/&gt; &lt;item name="s" row="2" col="10" tabindex="1" sequence="2"/&gt; &lt;item name="z" row="8" col="15" tabindex="" sequence=""/&gt; &lt;/items&gt; </code></pre> <p><strong>the wanted, correctly sorted result is produced</strong>:</p> <pre><code>&lt;items&gt; &lt;item row="0" col="9"/&gt; &lt;item row="1" col="5"/&gt; &lt;item row="2" col="5"/&gt; &lt;item row="5" col="9"/&gt; &lt;item row="20" col="9"/&gt; &lt;item name="a" row="7" col="8"/&gt; &lt;item name="c" row="5" col="9"/&gt; &lt;item name="d" row="5" col="6"/&gt; &lt;item name="d" row="20" col="12" tabindex="" sequence=""/&gt; &lt;item name="s" row="1" col="5" tabindex="3" sequence="4"/&gt; &lt;item name="s" row="2" col="10" tabindex="1" sequence="2"/&gt; &lt;item name="s" row="3" col="3" tabindex="1" sequence="2"/&gt; &lt;item name="s" row="3" col="3" tabindex="3" sequence="4"/&gt; &lt;item name="z" row="8" col="15" tabindex="" sequence=""/&gt; &lt;/items&gt; </code></pre> <p><strong>Do note</strong>:</p> <ol> <li><p><strong>Sorting is performed on</strong> <em>all</em> <strong>attributes specified in an external parameter</strong> (<code>$pSortTypes</code>). Compare this to the currently accepted answer, which only sorts on <code>@name</code> and <code>@row</code> and requires hardcoding of the order and sort data-type.</p></li> <li><p><strong>The exact wanted sorting order of the attributes can be specified</strong>. It is their order as in <code>$pSortTypes</code>.</p></li> <li><p><strong>The sort data-type for each attribute is specified</strong> in the <code>type</code> attribute in <code>$pSortTypes</code> (currently just <code>"alpha"</code> and <code>"numeric"</code>)</p></li> <li><p><strong>The maximum length of the string representation of the value of an attribute is specified</strong> as the <code>maxLength</code> attribute in <code>$pSortTypes</code>. This is used for correct padding/alignment and also increases the sorting efficiency.</p></li> <li><p><strong>This demonstrates how to solve even the most complicated sorting problems by having a user-defined <code>xsl:function</code></strong> (in this case <code>my:OrderedAttributeTuple()</code>) that generates a single sort key.</p></li> </ol>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload