title: XSLT Aggregation using sort with Muenchian Method for min and max
body: <p>I understand the Muenchian Method indexes the entire document at first read. But how can one sort prior or within grouping but not on its key? Specifically, how can I order a sibling of the key in order to calculate min and max of a series of element values?</p>
  
  <p>As XML data shows below, I am attempting to aggregate Companies by Industry. Across the seven metrics (revenue, assets, equity, netincome, stockprice, and employees) I can achieve various aggregates: sum with <code>sum()</code> and average with <code>sum() div count()</code>. But in order to obtain min and max particularly for netincome, I need to sort companies within industry by netincome and select the value at a <code>position()</code>. Do note, there are exactly five companies per industry. So for decreasing netincome sort, <code>position()=1</code> is the maximum and <code>position()=5</code> would be minimum.</p>
  
  <p>Now, I can achieve my desired results running <strong>two</strong> XSLT scripts. The first sorts  and second aggregates. But how can I do so with <strong>one</strong> XSLT? Within <code>for each loop</code> of Muenchian key I tried the below all to no avail. </p>
  
  <p><code>&lt;xsl:sort select="../netincome" data-type="number" order="descending"/&gt;</code></p>
  
  <p><code>&lt;xsl:sort select="key('indkey', .)/../netincome" data-type="number" order="descending"/&gt;</code></p>
  
  <p><code>&lt;xsl:sort select="key('indkey', .)[../netincome]" data-type="number" order="descending"/&gt;</code></p>
  
  <p>Possibly, the min and max must be done in a template outside the others or run two passes/call templates of the XSLT scripts  or using <code>&lt;xsl:with-params&gt;</code>.</p>
  
  <p><strong>XML data</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;data&gt;
      &lt;bigcompany&gt;
          &lt;company&gt;Company OA&lt;/company&gt;
          &lt;industry&gt;Oil &amp;amp; Gas&lt;/industry&gt;
          &lt;revenue&gt;394105000000&lt;/revenue&gt;
          &lt;assets&gt;349493000000&lt;/assets&gt;
          &lt;equity&gt;174399000000&lt;/equity&gt;
          &lt;netincome&gt;32520000000&lt;/netincome&gt;
          &lt;stockprice&gt;89.38&lt;/stockprice&gt;
          &lt;employees&gt;75300&lt;/employees&gt;
      &lt;/bigcompany&gt;
      &lt;bigcompany&gt;
          &lt;company&gt;Company OB&lt;/company&gt;
          &lt;industry&gt;Oil &amp;amp; Gas&lt;/industry&gt;
          &lt;revenue&gt;200494000000&lt;/revenue&gt;
          &lt;assets&gt;266026000000&lt;/assets&gt;
          &lt;equity&gt;156191000000&lt;/equity&gt;
          &lt;netincome&gt;19241000000&lt;/netincome&gt;
          &lt;stockprice&gt;108.62&lt;/stockprice&gt;
          &lt;employees&gt;64700&lt;/employees&gt;
      &lt;/bigcompany&gt;
      &lt;bigcompany&gt;
          &lt;company&gt;Company OC&lt;/company&gt;
          &lt;industry&gt;Oil &amp;amp; Gas&lt;/industry&gt;
          &lt;revenue&gt;13807000000&lt;/revenue&gt;
          &lt;assets&gt;4726000000&lt;/assets&gt;
          &lt;equity&gt;16445000000&lt;/equity&gt;
          &lt;netincome&gt;2720000000&lt;/netincome&gt;
          &lt;stockprice&gt;48.5&lt;/stockprice&gt;
          &lt;employees&gt;22000&lt;/employees&gt;
      &lt;/bigcompany&gt;
      &lt;bigcompany&gt;
          &lt;company&gt;Company OD&lt;/company&gt;
          &lt;industry&gt;Oil &amp;amp; Gas&lt;/industry&gt;
          &lt;revenue&gt;97800000000&lt;/revenue&gt;
          &lt;assets&gt;30500000000&lt;/assets&gt;
          &lt;equity&gt;10800000000&lt;/equity&gt;
          &lt;netincome&gt;2700000000&lt;/netincome&gt;
          &lt;stockprice&gt;27.53&lt;/stockprice&gt;
          &lt;employees&gt;45340&lt;/employees&gt;
      &lt;/bigcompany&gt;
      &lt;bigcompany&gt;
          &lt;company&gt;Company OE&lt;/company&gt;
          &lt;industry&gt;Oil &amp;amp; Gas&lt;/industry&gt;
          &lt;revenue&gt;62004000000&lt;/revenue&gt;
          &lt;assets&gt;117144000000&lt;/assets&gt;
          &lt;equity&gt;48427000000&lt;/equity&gt;
          &lt;netincome&gt;8428000000&lt;/netincome&gt;
          &lt;stockprice&gt;66.66&lt;/stockprice&gt;
          &lt;employees&gt;16900&lt;/employees&gt;
      &lt;/bigcompany&gt;
      &lt;bigcompany&gt;
          &lt;company&gt;Company PA&lt;/company&gt;
          &lt;industry&gt;Pharmaceuticals&lt;/industry&gt;
          &lt;revenue&gt;49605000000&lt;/revenue&gt;
          &lt;assets&gt;169274000000&lt;/assets&gt;
          &lt;equity&gt;71622000000&lt;/equity&gt;
          &lt;netincome&gt;9135000000&lt;/netincome&gt;
          &lt;stockprice&gt;30.14&lt;/stockprice&gt;
          &lt;employees&gt;78000&lt;/employees&gt;
      &lt;/bigcompany&gt;
      &lt;bigcompany&gt;
          &lt;company&gt;Company PB&lt;/company&gt;
          &lt;industry&gt;Pharmaceuticals&lt;/industry&gt;
          &lt;revenue&gt;48047000000&lt;/revenue&gt;
          &lt;assets&gt;105128000000&lt;/assets&gt;
          &lt;equity&gt;56943000000&lt;/equity&gt;
          &lt;netincome&gt;6272000000&lt;/netincome&gt;
          &lt;stockprice&gt;55.43&lt;/stockprice&gt;
          &lt;employees&gt;76000&lt;/employees&gt;
      &lt;/bigcompany&gt;
      &lt;bigcompany&gt;
          &lt;company&gt;Company PC&lt;/company&gt;
          &lt;industry&gt;Pharmaceuticals&lt;/industry&gt;
          &lt;revenue&gt;74331000000&lt;/revenue&gt;
          &lt;assets&gt;131119000000&lt;/assets&gt;
          &lt;equity&gt;69752000000&lt;/equity&gt;
          &lt;netincome&gt;16323000000&lt;/netincome&gt;
          &lt;stockprice&gt;102.31&lt;/stockprice&gt;
          &lt;employees&gt;126500&lt;/employees&gt;
      &lt;/bigcompany&gt;
      &lt;bigcompany&gt;
          &lt;company&gt;Company PD&lt;/company&gt;
          &lt;industry&gt;Pharmaceuticals&lt;/industry&gt;
          &lt;revenue&gt;23113000000&lt;/revenue&gt;
          &lt;assets&gt;35249000000&lt;/assets&gt;
          &lt;equity&gt;17641000000&lt;/equity&gt;
          &lt;netincome&gt;4685000000&lt;/netincome&gt;
          &lt;stockprice&gt;67.2&lt;/stockprice&gt;
          &lt;employees&gt;37925&lt;/employees&gt;
      &lt;/bigcompany&gt;
      &lt;bigcompany&gt;
          &lt;company&gt;Company PE&lt;/company&gt;
          &lt;industry&gt;Pharmaceuticals&lt;/industry&gt;
          &lt;revenue&gt;15879000000&lt;/revenue&gt;
          &lt;assets&gt;33749000000&lt;/assets&gt;
          &lt;equity&gt;14852000000&lt;/equity&gt;
          &lt;netincome&gt;2004000000&lt;/netincome&gt;
          &lt;stockprice&gt;58&lt;/stockprice&gt;
          &lt;employees&gt;28000&lt;/employees&gt;
      &lt;/bigcompany&gt;
      &lt;bigcompany&gt;
          &lt;company&gt;Company MA&lt;/company&gt;
          &lt;industry&gt;Media&lt;/industry&gt;
          &lt;revenue&gt;48813000000&lt;/revenue&gt;
          &lt;assets&gt;84186000000&lt;/assets&gt;
          &lt;equity&gt;44958000000&lt;/equity&gt;
          &lt;netincome&gt;8004000000&lt;/netincome&gt;
          &lt;stockprice&gt;93.65&lt;/stockprice&gt;
          &lt;employees&gt;180000&lt;/employees&gt;
      &lt;/bigcompany&gt;
      &lt;bigcompany&gt;
          &lt;company&gt;Company MB&lt;/company&gt;
          &lt;industry&gt;Media&lt;/industry&gt;
          &lt;revenue&gt;64657000000&lt;/revenue&gt;
          &lt;assets&gt;158813000000&lt;/assets&gt;
          &lt;equity&gt;51058000000&lt;/equity&gt;
          &lt;netincome&gt;7135000000&lt;/netincome&gt;
          &lt;stockprice&gt;57.05&lt;/stockprice&gt;
          &lt;employees&gt;139000&lt;/employees&gt;
      &lt;/bigcompany&gt;
      &lt;bigcompany&gt;
          &lt;company&gt;Company MC&lt;/company&gt;
          &lt;industry&gt;Media&lt;/industry&gt;
          &lt;revenue&gt;31867000000&lt;/revenue&gt;
          &lt;assets&gt;54793000000&lt;/assets&gt;
          &lt;equity&gt;17418000000&lt;/equity&gt;
          &lt;netincome&gt;4514000000&lt;/netincome&gt;
          &lt;stockprice&gt;36.52&lt;/stockprice&gt;
          &lt;employees&gt;27000&lt;/employees&gt;
      &lt;/bigcompany&gt;
      &lt;bigcompany&gt;
          &lt;company&gt;TCompany MD&lt;/company&gt;
          &lt;industry&gt;Media&lt;/industry&gt;
          &lt;revenue&gt;29795000000&lt;/revenue&gt;
          &lt;assets&gt;67994000000&lt;/assets&gt;
          &lt;equity&gt;29904000000&lt;/equity&gt;
          &lt;netincome&gt;3691000000&lt;/netincome&gt;
          &lt;stockprice&gt;84.3&lt;/stockprice&gt;
          &lt;employees&gt;26000&lt;/employees&gt;
      &lt;/bigcompany&gt;
      &lt;bigcompany&gt;
          &lt;company&gt;Company ME&lt;/company&gt;
          &lt;industry&gt;Media&lt;/industry&gt;
          &lt;revenue&gt;15284000000&lt;/revenue&gt;
          &lt;assets&gt;26387000000&lt;/assets&gt;
          &lt;equity&gt;9966000000&lt;/equity&gt;
          &lt;netincome&gt;1879000000&lt;/netincome&gt;
          &lt;stockprice&gt;54.88&lt;/stockprice&gt;
          &lt;employees&gt;20915&lt;/employees&gt;
      &lt;/bigcompany&gt;
  &lt;/data&gt;
  </code></pre>
  
  <p><strong>XSLT 1</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
   &lt;xsl:output omit-xml-declaration="yes" indent="yes"/&gt;
   &lt;xsl:strip-space elements="*"/&gt;    
  
    &lt;xsl:template match="data"&gt;
      &lt;xsl:copy&gt;
        &lt;xsl:apply-templates&gt;        
          &lt;xsl:sort select="industry" order="ascending"/&gt;
          &lt;xsl:sort select="netincome" data-type="number" order="descending"/&gt; 
        &lt;/xsl:apply-templates&gt;
      &lt;/xsl:copy&gt;
    &lt;/xsl:template&gt;
  
    &lt;/xsl:stylesheet&gt;
  </code></pre>
  
  <p><strong>XSLT 2</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
   &lt;xsl:output omit-xml-declaration="yes" indent="yes"/&gt;
   &lt;xsl:strip-space elements="*"/&gt; 
  
    &lt;xsl:key name="indkey" match="bigcompany/industry" use="."/&gt;
  
    &lt;xsl:template match="data"&gt;
      &lt;data&gt;
      &lt;xsl:for-each select="bigcompany/industry[generate-id()    
                           = generate-id(key('indkey', .)[1])]"&gt;  
        &lt;xsl:sort select="." order="ascending"/&gt;                    
  
          &lt;aggdata&gt;
            &lt;xsl:copy-of select="."/&gt;        
            &lt;SumOfRevenue&gt;&lt;xsl:copy-of select="sum(key('indkey', .)/../revenue)"/&gt;&lt;/SumOfRevenue&gt;
            &lt;AvgOfAssets&gt;&lt;xsl:copy-of select="sum(key('indkey', .)/../assets) div count(key('indkey', .)/../assets)"/&gt;&lt;/AvgOfAssets&gt;
            &lt;AvgOfEquity&gt;&lt;xsl:copy-of select="sum(key('indkey', .)/../equity) div count(key('indkey', .)/../equity)"/&gt;&lt;/AvgOfEquity&gt;
            &lt;MaxOfIncome&gt;&lt;xsl:value-of select="key('indkey', .)[1]/../netincome"/&gt;&lt;/MaxOfIncome&gt;
            &lt;MinOfIncome&gt;&lt;xsl:value-of select="key('indkey', .)[5]/../netincome"/&gt;&lt;/MinOfIncome&gt;
            &lt;AvgOfStockPrice&gt;&lt;xsl:copy-of select="sum(key('indkey', .)/../stockprice) div count(key('indkey', .)/../stockprice)"/&gt;&lt;/AvgOfStockPrice&gt;
            &lt;SumOfEmployees&gt;&lt;xsl:copy-of select="sum(key('indkey', .)/../employees)"/&gt;&lt;/SumOfEmployees&gt;
          &lt;/aggdata&gt;
  
      &lt;/xsl:for-each&gt;
  
      &lt;/data&gt;
    &lt;/xsl:template&gt;
  &lt;/xsl:stylesheet&gt;
  </code></pre>
  
  <p><strong>Final and Desired results</strong>  <em>- but how with one XSLT?</em></p>
  
  <pre><code>&lt;?xml version='1.0' encoding='UTF-8'?&gt;
  &lt;data&gt;
    &lt;aggdata&gt;
      &lt;industry&gt;Media&lt;/industry&gt;
      &lt;SumOfRevenue&gt;1.90416e+011&lt;/SumOfRevenue&gt;
      &lt;AvgOfAssets&gt;7.84346e+010&lt;/AvgOfAssets&gt;
      &lt;AvgOfEquity&gt;3.06608e+010&lt;/AvgOfEquity&gt;
      &lt;MaxOfIncome&gt;8004000000&lt;/MaxOfIncome&gt;
      &lt;MinOfIncome&gt;1879000000&lt;/MinOfIncome&gt;
      &lt;AvgOfStockPrice&gt;65.28&lt;/AvgOfStockPrice&gt;
      &lt;SumOfEmployees&gt;392915&lt;/SumOfEmployees&gt;
    &lt;/aggdata&gt;
    &lt;aggdata&gt;
      &lt;industry&gt;Oil &amp;amp; Gas&lt;/industry&gt;
      &lt;SumOfRevenue&gt;7.6821e+011&lt;/SumOfRevenue&gt;
      &lt;AvgOfAssets&gt;1.535778e+011&lt;/AvgOfAssets&gt;
      &lt;AvgOfEquity&gt;8.12524e+010&lt;/AvgOfEquity&gt;
      &lt;MaxOfIncome&gt;32520000000&lt;/MaxOfIncome&gt;
      &lt;MinOfIncome&gt;2700000000&lt;/MinOfIncome&gt;
      &lt;AvgOfStockPrice&gt;68.138&lt;/AvgOfStockPrice&gt;
      &lt;SumOfEmployees&gt;224240&lt;/SumOfEmployees&gt;
    &lt;/aggdata&gt;
    &lt;aggdata&gt;
      &lt;industry&gt;Pharmaceuticals&lt;/industry&gt;
      &lt;SumOfRevenue&gt;2.10975e+011&lt;/SumOfRevenue&gt;
      &lt;AvgOfAssets&gt;9.49038e+010&lt;/AvgOfAssets&gt;
      &lt;AvgOfEquity&gt;4.6162e+010&lt;/AvgOfEquity&gt;
      &lt;MaxOfIncome&gt;16323000000&lt;/MaxOfIncome&gt;
      &lt;MinOfIncome&gt;2004000000&lt;/MinOfIncome&gt;
      &lt;AvgOfStockPrice&gt;62.616&lt;/AvgOfStockPrice&gt;
      &lt;SumOfEmployees&gt;346425&lt;/SumOfEmployees&gt;
    &lt;/aggdata&gt;
  &lt;/data&gt;
  </code></pre>