[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] Complex sorting problem (looking for an XSLT outer join?)


Subject: Re: [xsl] Complex sorting problem (looking for an XSLT outer join?)
From: Dimitre Novatchev <dnovatchev@xxxxxxxxx>
Date: Thu, 16 Jan 2003 12:07:16 -0800 (PST)

Here's one solution, which is simple enough and doesn't need the
xx:node-set() extension function.

This transformation:

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
  
  <xsl:key name="kWeight" match="@weight" use="../@id"/>
  
  <xsl:template match="/">
    <xsl:for-each select="/*/items/item">
      <xsl:sort 
       select="concat('0',key('kWeight', @category) )
                     + 1 * (1 - count(key('kWeight', 
                                          @category
                                          )
                                      )
                            )"/>
      
      <xsl:copy-of select="."/>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

When applied on your source.xml (corrected to be well-formed):

<root>    
  <items>        
    <item category="1" data="ggg">            
      <date year="1995" month="4" day="13"/>        
    </item>        
    <item category="2" data="hhh">            
      <date year="1984" month="7" day="22"/>        
    </item>        
    <item category="3" data="www">            
      <date year="1991" month="3" day="12"/>        
    </item>        
    <item category="3" data="rrr">            
      <date year="1999" month="6" day="19"/>        
    </item>        
    <item category="4" data="xxx">            
      <date year="1982" month="2" day="17"/>        
    </item>        
    <item category="5" data="kkk">            
      <date year="2000" month="12" day="11"/>        
    </item>    
  </items>    
  <categories>        
    <category id="1" weight="0"/>        
    <category id="3" weight="2"/>        
    <category id="4" weight="1"/>    
  </categories>
</root>

produces this result:

<item category="1" data="ggg">            
      <date year="1995" month="4" day="13" />        
    </item>
<item category="2" data="hhh">            
      <date year="1984" month="7" day="22" />        
    </item>
<item category="4" data="xxx">            
      <date year="1982" month="2" day="17" />        
    </item>
<item category="5" data="kkk">            
      <date year="2000" month="12" day="11" />        
    </item>
<item category="3" data="www">            
      <date year="1991" month="3" day="12" />        
    </item>
<item category="3" data="rrr">            
      <date year="1999" month="6" day="19" />        
    </item>


So, the items are correctly sorted according to the weight of the
corresponding category, or if the category is missing, then to the
default weight (1).

I haven't coded the additional sort by date, leaving this as an
exercise.



=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL



"Taras Tielkes" <taras@xxxxxxx> wrote in message
news:DEA593548993924AAEA173FE34217C170F0E06@xxxxxxxxxxxxxxxxxxx
> Hi,
> 
> My source xml has the following format:
> 
> <root>
>     <items>
>         <item category="1" data="ggg">
>             <date year="1995" month="4" day="13"/>
>         </item>
>         <item category="2" data="hhh">
>             <date year="1984" month="7" day="22"/>
>         </item>
>         <item category="3" data="www">
>             <date year="1991" month="3" day="12"/>
>         </item>
>         <item category="3" data="rrr">
>             <date year="1999" month="6" day="19"/>
>         </item>
>         <item category="4" data="xxx">
>             <date year="1982" month="2" day="17"/>
>         </item>
>         <item category="5" data="kkk">
>             <date year="2000" month="12" day="11"/>
>         </item>
>     </items>
>     
>     <categories>
>         <category id="1" weight="0">
>         <category id="3" weight="2">
>         <category id="4" weight="1">
>     </categories>
> </root>
> 
> 1) The source xml contains a list of items.
>    Each item carries a 'data' attribute, which is the actual content
of the
> item.
>    Apart from that, each item contains:
>    a) a 'catagory' attribute, identifying the catagory that the item
belogs
> to.
>    b) a 'date' child element, representing the date of the item
>    Each item has an implied weight, implied by the category that it
> references. (but see [2] and [3])
>    
> 2) The source xml also contains a list of categories.
>    Each category contains a 'weight' attribute, which carries the
> 'importance' of the category.
>    Weight is from 0 (least important) to 2 (most important), in other
words
> [0,2].
>    
> 3) Some of the categories referred to by the item elements are not
present
> in the source xml.
>    A default weight of 1 should be assumed in that case.
>    In the example xml, the categories (2,5) are absent.
>        
> I would like to sort the item elements using the following criteria:
>    1) first, by (implied) weight
>    2) second, by date
>    
> It seems to me that the problem would be easy if all referenced
categories
> were present in the source xml.
> In that case, I could use xsl:key to retreive the matching weight for
each
> item.
> 
> However, that is not the case. It seems that what I want is to grab a
> default weight of 1 wherever the references category is not present
in the
> source xml.
> Using SQL, for instance, I could use an outer join, specifying a
default
> value.
>     
> Is there any solution for this problem in XSLT?
>     
> Thanks in advance for any feedback,
>     
> tt


__________________________________________________
Do you Yahoo!?
Yahoo! Mail Plus - Powerful. Affordable. Sign up now.
http://mailplus.yahoo.com

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list



Current Thread
Keywords
xml