[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

RE: Complex sorting problem (looking for an XSLT outer

Subject: RE: Complex sorting problem (looking for an XSLT outer join?)
From: Taras Tielkes <taras@xxxxxxx>
Date: Thu, 16 Jan 2003 21:02:40 +0100
xsl sort complex
Hi Philippe,

If we assume that I want to restrict myself to XSLT 1.0, do you think it
would be possible to write something with more elegance than the following
monstrosity?

tt

<?xml version="1.0"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
	
	<xsl:output method="html"/>
	
	<xsl:key name="weight" match="/root/categories/category/@weight"
use="../@id"/>

	<xsl:variable name="match2"
select="/root/items/item[key('weight',@category)=2]"/>
	<xsl:variable name="match1"
select="/root/items/item[key('weight',@category)=1]"/>
	<xsl:variable name="match0"
select="/root/items/item[key('weight',@category)=0]"/>
	<xsl:variable name="missing"
select="/root/items/item[not(key('weight',@category))]"/>
	<xsl:variable name="match1all" select="$match1|$missing"/>

	<xsl:template match="/">
		<table border="1">
			<tr>
				<td><b>data</b></td>
				<td><b>weight</b></td>
				<td><b>date</b></td>
			</tr>
			<xsl:for-each select="$match2[position() &lt; 5]">
				<xsl:sort select="date/@year"
order="descending" data-type="number"/>
				<xsl:sort select="date/@month"
order="descending" data-type="number"/>
				<xsl:sort select="date/@day"
order="descending" data-type="number"/>
				<xsl:call-template name="dump-item">
					<xsl:with-param name="item"
select="."/>
				</xsl:call-template>
			</xsl:for-each>
			<xsl:for-each select="$match1all[position() &lt;
(5-count($match2))]">
				<xsl:sort select="date/@year"
order="descending" data-type="number"/>
				<xsl:sort select="date/@month"
order="descending" data-type="number"/>
				<xsl:sort select="date/@day"
order="descending" data-type="number"/>
				<xsl:call-template name="dump-item">
					<xsl:with-param name="item"
select="."/>
				</xsl:call-template>
			</xsl:for-each>
			<xsl:for-each select="$match0[position() &lt;
(5-count($match2)-count(match1all))]">
				<xsl:sort select="date/@year"
order="descending" data-type="number"/>
				<xsl:sort select="date/@month"
order="descending" data-type="number"/>
				<xsl:sort select="date/@day"
order="descending" data-type="number"/>
				<xsl:call-template name="dump-item">
					<xsl:with-param name="item"
select="."/>
				</xsl:call-template>
			</xsl:for-each>
		</table>
		
	</xsl:template>
	
	<xsl:template name="dump-item">
		<xsl:param name="item"/>
		<tr>
			<td>
				<xsl:value-of select="$item/@data"/>
			</td>
			<td>
				<xsl:value-of
select="key('weight',$item/@category)"/>
			</td>		
			<td>
				<xsl:value-of select="date/@year"/>
				<xsl:text>/</xsl:text>
				<xsl:value-of select="date/@month"/>
				<xsl:text>/</xsl:text>
				<xsl:value-of select="date/@day"/>
			</td>
		</tr>	
	</xsl:template>

</xsl:stylesheet>

:-)

> -----Original Message-----
> From: Philippe Drix [mailto:pdrix@xxxxxxxxxxxx]
> Sent: Thursday, January 16, 2003 7:13 PM
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: Re:  Complex sorting problem (looking for an XSLT outer
> join?)
> 
> 
> At 18:43 16/01/2003 +0100, you wrote:
> >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
> >
> >
> >
> >
> >
> >
> >
> >  XSL-List info and archive:  
http://www.mulberrytech.com/xsl/xsl-list


You can copy your XML into a variable, but with a copy that will not be a 
true copy, because you will have to instanciate attribute "weight", 
defaulted to value 1 if absent.
Then you put the current node on the root of this variable (use Saxon with 
version="1.1", or use a function like node-set() to convert RTF to 
nodes-set ):
<xsl:for-each select="$myNewXMLtreeWithAttributeWeightAlwaysPresent">
         <xsl:for-each select="what you want">
                 <xsl:sort what you want>
         </xsl:for-each>
</xsl:for-each>
Regards -- Ph D

==
Philippe Drix
      ___________
__| OBJECTIVA |___________________
http://www.objectiva.fr
21-23, rue Aristide Briand - 92170 Vanves
tel : +33 1 47 36 60 30
fax : +33 1 47 36 61 93



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

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


Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.