Re: [xsl] Newbie question on XSL transformations: multiple sorts on element attributes

Subject: Re: [xsl] Newbie question on XSL transformations: multiple sorts on element attributes
From: Rob Newman <rlnewman@xxxxxxxx>
Date: Tue, 6 Feb 2007 14:24:22 -0800
Hi Abel,

I am chewing this over now - thanks for the help. Just to clarify a few points:


<xsl:template match="sources"> <xsl:element name="dataloggerlist"> <xsl:for-each select="source"> <xsl:apply-templates select="/pfarr/pfarr/pfarr" /> </xsl:for-each> </xsl:element> </xsl:template>

"sources" never matches anything. This template does nothing (or your input contains more).

I left some information out. I am actually importing data from 4 different XML files so I created a summary file (summary.xml) that consists of a parent element called 'sources' and child elements named 'source' that locally reference the URLs of all the XML files I need.


summary.xml:
<sources>
    <source href="file1.xml" />
    <source href="file2.xml" />
    <source href="file3.xml" />
    <source href="file4.xml" />
</sources>


The triple path is not needed, because you already select this same path. What you are saying to the XSLT processor here is: any "pfarr" (most right in the match) that has a parent "pfarr" (middle) that has a parent "pfarr". Since you already do a select="pfarr/pfarr/pfarr", which only selects the 'pfarr' children of the 'pfarr' children of 'pfarr', there is no need to let the processor do this extra parent check.

That is a great tip - I have implemented this and it works.


<xsl:sort select="param/@id{dlt}" data-type="number" order="descending" />
<xsl:sort select="@name" order="ascending" />

I see now that you want to:


1. put all elements with id = 'dlt' first
2. order these first elements by number value
3. next, order all other elements, not containing 'dlt' by there id

Almost! I have a whole series of pfarr elements. Each one has a pfstring element that has an id='dlt' and and value. Example:


<pfstring id='dlt'>20</pfstring>

So what I want is to check the value of the element pfstring who's id is 'dlt', and sort based on this.

Example:

<pfarr name="A">
	<pfstring id="dlt">20</pfstring>
</pfarr>

<pfarr name="B">
	<pfstring id="dlt">80</pfstring>
</pfarr>

<pfarr name="C">
	<pfstring id="dlt">50</pfstring>
</pfarr>

<pfarr name="D">
	<pfstring id="dlt">50</pfstring>
</pfarr>


I want this to be output thus:


<datalogger name="B">
	<param id="dlt">80</param>
</datalogger>

<datalogger name="C">
	<param id="dlt">50</param>
</datalogger>

<datalogger name="D">
	<param id="dlt">50</param>
</datalogger>

<datalogger name="A">
	<param id="dlt">20</param>
</datalogger>

To be verbose: I want to sort them so that the first datalogger element in the XML output is the one with the highest dlt. This is then followed by those with high dlt values. Once we get beyond the dlt values, the datalogger elements are ordered by their name. All dataloggers have a param element with an id of 'dlt' and an associated value.

This looks like this, in XSLT (but is not trivial)

<xsl:sort select="@name = 'dlt'" order="descending"/>
<xsl:sort select="self::node()[@name = 'dlt']" data- type="number" order="ascending"/>
<xsl:sort select="@name" />


Finally, this is the complete stylesheet that does what you want:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/ Transform">
<xsl:output indent="yes" />
<xsl:template match="/">
<xsl:apply-templates select="pfarr/pfarr/pfarr" />


</xsl:template>
<xsl:template match="pfarr">
<datalogger name="{@name}">
<xsl:apply-templates select="pfstring">
<xsl:sort select="@name = 'dlt'" order="descending"/>
<xsl:sort select="self::node()[@name = 'dlt']" data- type="number" order="ascending"/>
<xsl:sort select="@name" />
</xsl:apply-templates>
</datalogger>
</xsl:template>


  <xsl:template match="pfstring">
      <param id="{@name}" >
          <xsl:value-of select="." />
      </param>
  </xsl:template>
</xsl:stylesheet>

I am rapidly working through this (with Jeni Tennison's book next to me!) and trying to decipher it to my newbie-mentality. Again, I really appreciate all the help.


Sincerely,
- Rob

Current Thread