title: Sort XML-elements by their attributes
body: <p>My question is very similar to those:</p>
  
  <ol>
  <li><a href="https://stackoverflow.com/questions/8267147/xslt-to-sort-on-value-of-multiple-attributes">List item</a></li>
  <li><a href="https://stackoverflow.com/questions/35796556/xls-sort-xml-nodes-by-attribute">List item</a></li>
  <li><a href="https://coderanch.com/t/564812/languages/sort-child-elements-based-attribute" rel="nofollow noreferrer">List item</a></li>
  <li><a href="https://stackoverflow.com/questions/14647638/xslt-sorting-how-to-sort-xml-childnodes-inside-a-parent-node-with-an-attribute">List item</a></li>
  <li><a href="https://stackoverflow.com/questions/15790089/sort-xml-elements-by-certain-attributes">List item</a></li>
  </ol>
  
  <p>However, they don't give the answer to my particular case. Although eventually, I solved the problem but I don't feel this solution to be good and would appreciate if there are better ways to do this. I faced the sort-problem for the first time and would like to understand it better.</p>
  
  <p><strong>From this (modelled) input:</strong></p>
  
  <pre><code>&lt;root&gt;
      &lt;measure attribute="attr"&gt;
          &lt;other n="234"&gt;-&lt;/other&gt;
          &lt;other n="345"&gt;-&lt;/other&gt;
          &lt;element n="2"/&gt;
          &lt;element n="1"/&gt;
          &lt;element n="3"/&gt;
          &lt;other attr="abc"&gt;-&lt;/other&gt;
      &lt;/measure&gt;
      &lt;measure&gt;
          &lt;other n="234"&gt;-&lt;/other&gt;
          &lt;other n="345"&gt;&lt;node/&gt;&lt;/other&gt;
          &lt;element n="3"/&gt;
          &lt;element n="1"/&gt;
          &lt;element n="2"/&gt;
          &lt;other attr="abc"&gt;-&lt;/other&gt;
      &lt;/measure&gt;
  &lt;/root&gt;
  </code></pre>
  
  <p><strong>I want to get this result:</strong></p>
  
  <pre><code>&lt;root&gt;
     &lt;measure&gt;
        &lt;other n="234"&gt;-&lt;/other&gt;
        &lt;other n="345"&gt;-&lt;/other&gt;
        &lt;element n="1"/&gt;
        &lt;element n="2"/&gt;
        &lt;element n="3"/&gt;
        &lt;other attr="abc"&gt;-&lt;/other&gt;
     &lt;/measure&gt;
     &lt;measure&gt;
        &lt;other n="234"&gt;-&lt;/other&gt;
        &lt;other n="345"&gt;
           &lt;node/&gt;
        &lt;/other&gt;
        &lt;node/&gt;
        &lt;element n="1"/&gt;
        &lt;element n="2"/&gt;
        &lt;element n="3"/&gt;
        &lt;other attr="abc"&gt;-&lt;/other&gt;
     &lt;/measure&gt;
  &lt;/root&gt;
  </code></pre>
  
  <p>So I want to get particular elements (<code>&lt;element/&gt;</code>) to be sorted in the relation to each other, but other elements should stay on their positions.</p>
  
  <p>First I tried this: <a href="https://xsltfiddle.liberty-development.net/6r5Gh3h/3" rel="nofollow noreferrer">https://xsltfiddle.liberty-development.net/6r5Gh3h/3</a></p>
  
  <pre><code>&lt;xsl:stylesheet  version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
  
      &lt;xsl:output encoding="UTF-8" indent="yes" method="xml"/&gt;
      &lt;xsl:strip-space elements="*"/&gt;
      &lt;xsl:mode on-no-match="shallow-copy"/&gt;
  
      &lt;xsl:template match="measure"&gt;  
          &lt;xsl:copy&gt;
              &lt;xsl:apply-templates select="@*, node()[local-name()!='element']"/&gt;
              &lt;xsl:apply-templates  select="element"&gt;
                  &lt;xsl:sort order="ascending" select="@n"/&gt;
              &lt;/xsl:apply-templates&gt;
          &lt;/xsl:copy&gt;     
      &lt;/xsl:template&gt;
  &lt;/xsl:stylesheet&gt;
  </code></pre>
  
  <p>But it changed the order of the elements.</p>
  
  <p>This solution makes the desired output but are there better ways to do this?</p>
  
  <p><a href="https://xsltfiddle.liberty-development.net/94rmq6j" rel="nofollow noreferrer">https://xsltfiddle.liberty-development.net/94rmq6j</a></p>
  
  <pre><code>&lt;xsl:stylesheet exclude-result-prefixes="xs math map array" version="3.0" xmlns:array="http://www.w3.org/2005/xpath-functions/array" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:math="http://www.w3.org/2005/xpath-functions/math" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
  
  &lt;xsl:output encoding="UTF-8" indent="yes" method="xml"/&gt;
  &lt;xsl:strip-space elements="*"/&gt;
  &lt;xsl:mode on-no-match="shallow-copy"/&gt;
  
  &lt;xsl:template match="measure"&gt;
      &lt;xsl:copy&gt;
          &lt;xsl:variable name="sortedEls"&gt;
              &lt;xsl:perform-sort select="child::element"&gt;
                  &lt;xsl:sort data-type="number" order="ascending" select="@n"/&gt;
              &lt;/xsl:perform-sort&gt;
          &lt;/xsl:variable&gt;
  
          &lt;xsl:for-each select="descendant::*"&gt;
              &lt;xsl:choose&gt;
                  &lt;xsl:when test="local-name() = 'element' and not(following-sibling::element)"&gt;
                      &lt;xsl:sequence select="$sortedEls"/&gt;
                  &lt;/xsl:when&gt;
                  &lt;xsl:otherwise&gt;
                      &lt;xsl:if test="local-name() != 'element'"&gt;
                          &lt;xsl:apply-templates select="."/&gt;
                      &lt;/xsl:if&gt;
                  &lt;/xsl:otherwise&gt;
              &lt;/xsl:choose&gt;
          &lt;/xsl:for-each&gt;
  
      &lt;/xsl:copy&gt;
  &lt;/xsl:template&gt;
  </code></pre>
  
  <p></p>