xsl-list
[Top] [All Lists]

Re: Sorting problem

2005-08-31 04:36:44
On 8/31/05, Joe Fawcett <joefawcett(_at_)hotmail(_dot_)com> wrote:
Dear All

Supposing I have a document such as below =>
<root>
 <item type="A" subType="1"/>
 <item type="A" subType="2"/>
 <item type="A" subType="4"/>
 <item type="B" subType="2"/>
 <item type="B" subType="3"/>
 <item type="D" subType="1"/>
 <item type="D" subType="2"/>
 <item type="D" subType="3"/>
 <item type="D" subType="4"/>
 <item type="E" subType="2"/>
 <item type="E" subType="4"/>
</root>

This is sorted by @type and then @subType, the subType can be any positive
number, not just an integer.

I need to select the first occurrence of each item, based on its @subType,
then the second, then the third etc, keeping them in alphabetical order
based on @type =>

<root>
 <item type="A" subType="1"/>
 <item type="B" subType="2"/>
 <item type="D" subType="1"/>
 <item type="E" subType="2"/>
 <item type="A" subType="2"/>
 <item type="B" subType="3"/>
 <item type="D" subType="2"/>
 <item type="E" subType="4"/>
 <item type="A" subType="4"/>
 <item type="D" subType="3"/>
 <item type="D" subType="4"/>
</root>

This is the result of converting a RTF via xx:node-set, I am stuck with
version 1.0, so as far as I understand I cannot use keys in the solution.


I have produced a working solution but it seems inelegant. I first select a
distinct list of @type using pre-Muenchian methods where the type doesn't
have a preceding-sibling of the same value. I then call a template by name
recursively whereby the first pass iterates through the distinct list using
for-each and selects the the first <item> that matches the type. This
template is then called again and does the same for the second matching item
and continues in the same fashion. The recursion stops after being called
sufficient times to ensure each item is matched once.

Can anyone suggest anything more appealing?


This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 exclude-result-prefixes="msxsl"

        <xsl:output omit-xml-declaration="yes" indent="yes"/>
        
        <xsl:key name="kTypes" match="@type" use="."/>
        <xsl:key name="kItemByType" match="item" use="@type"/>
         
        <xsl:variable name="vDoc" select="/"/>

        <xsl:variable name="vrtfdistTypes">
          <xsl:for-each select=
            "/*/item/@type
                [generate-id() 
                = 
                 generate-id(key('kTypes', .)[1])
                 ]">
             <type code="{.}" count="{count(key('kTypes', .))}"/>
    </xsl:for-each>
        </xsl:variable>
        
        <xsl:variable name="vdistTypes" 
select="msxsl:node-set($vrtfdistTypes)/*"/>
        
        <xsl:variable name="vmaxCount" 
         select="number($vdistTypes[not(@count &lt; 
$vdistTypes/@count)]/@count)"/>
        
        <xsl:variable name="vmaxCountTypecode" 
         select="$vdistTypes[not(@count &lt; $vdistTypes/@count)]/@code[1]"/>
        
        <xsl:template match="/">
         <items>
          <xsl:for-each select="key('kItemByType', $vmaxCountTypecode)">
            <xsl:variable name="vcurTuple" select="position()"/>
            <xsl:for-each select="$vdistTypes">
              <xsl:variable name="vthisType" select="."/>
              <xsl:for-each select="$vDoc">
                <xsl:copy-of select=
                   "key('kItemByType', $vthisType/@code)[$vcurTuple]"/>
              </xsl:for-each>
            </xsl:for-each>
          </xsl:for-each>
         </items>
        </xsl:template>
        
</xsl:stylesheet>

when applied on this source xml:

<root>
        <item type="A" subType="1"/>
        <item type="A" subType="2"/>
        <item type="A" subType="4"/>
        <item type="B" subType="2"/>
        <item type="B" subType="3"/>
        <item type="D" subType="1"/>
        <item type="D" subType="2"/>
        <item type="D" subType="3"/>
        <item type="D" subType="4"/>
        <item type="E" subType="2"/>
        <item type="E" subType="4"/>
</root>

produces the wanted result:

<items>
  <item type="A" subType="1" />
  <item type="B" subType="2" />
  <item type="D" subType="1" />
  <item type="E" subType="2" />
  <item type="A" subType="2" />
  <item type="B" subType="3" />
  <item type="D" subType="2" />
  <item type="E" subType="4" />
  <item type="A" subType="4" />
  <item type="D" subType="3" />
  <item type="D" subType="4" />
</items>


Cheers,
Dimitre Novatchev.

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



<Prev in Thread] Current Thread [Next in Thread>