Re: sorting nodes in reverse document order

Subject: Re: sorting nodes in reverse document order
From: Ann Marie Rubin - Sun PC Networking Engineering <Annmarie.Rubin@xxxxxxxxxxxx>
Date: Wed, 17 May 2000 09:48:20 -0400 (EDT)
Jeni,

Thank you so much for your help.  Your solutions worked perfectly.  More 
importantly, I now finally understand the recursive power of templates. I was 
trying to do a lot of unnecessary coding because I didn't understand what the 
apply-templates could do.

I've switched to keys and the stylesheet does run faster.  

Thanks again.

Ann Marie

	X-Sender: JTennison@NTServer
	To: Ann Marie Rubin - Sun PC Networking Engineering 
<Annmarie.Rubin@xxxxxxxxxxxx>
	From: Jeni Tennison <Jeni.Tennison@xxxxxxxxxxxxxxxx>
	Subject: Re: sorting nodes in reverse document order
	Cc: xsl-list@xxxxxxxxxxxxxxxx
	Mime-Version: 1.0
	X-MDaemon-Deliver-To: Annmarie.Rubin@xxxxxxxxxxxx
	
	Ann,
	
	>Thanks for your suggestions.  The <xsl:template match="CLASS"
	mode="hierarchy"> 
	>rule that you suggested seems to select the parent (@SUPERCLASS) of 
each
	class 
	>element in the XML source tree.  
	
	That's right.  It generates details for its parent before it prints out
	details of itself.  Because it's recursive, generating details of the
	parent, in turn generates details of *its* parent, and its parent, and 
so
	on, walking up the hierarchy.  That means that the details of the nodes 
are
	outputted in the right order, with the one at the top of the hierarchy
	first and the class we're currently talking about last.
	
	>What I want to do is match each CLASS, output some CLASS data, then 
print
	the 
	>ancestors for the matched class (not all classes in the hierarchy). The 
	>following code does output the ancestors for each class, but in 
document
	order.  
	>I need to output the ancestors in reverse document order.
	
	[Just to be clear - I think you mean that you want to output the 
ancestors
	in reverse hierarchy order rather than 'reverse document order' - the
	classes might be arranged in a hierarchy within a document, or they 
might
	not.  The method that I'm proposing doesn't rely on any particular order
	for the classes within the original XML document.]
	
	OK, looking again, you can do it with a named template in the same way 
as
	with the template mode by adding the (recursive) details of the parent
	*before* the details of the child.  Your code becomes:
	
	<xsl:template match="CLASS">
	 ...
	 outputs some class data
	 ...
	 
	<h2>Class Hierarchy</h2>
	<!-- Call hierarchy template to output ancestors of this class -->
	<xsl:call-template name="hierarchy"/>
	
	<!-- named template to do the hierarchy tracing -->
	<xsl:template name="hierarchy">
	<!-- xsl:param must be first thing in template, not embedded within 
xsl:if -->
	<xsl:param name="parentname" select="@SUPERCLASS"/>
	<!-- parent details first (recursively) -->
	<xsl:if test="@SUPERCLASS">
	  <xsl:for-each select="//CLASS[@NAME=$parentname]">
	       <xsl:call-template name="hierarchy"/>
	  </xsl:for-each>
	</xsl:if>
	<!-- then child details -->
	<br data="{@NAME} -- {@SUPERCLASS}"><a href="{@NAME}.html"><xsl:value-of
	select="@NAME"/></a></br>
	</xsl:template>
	
	As I said before, if the XSL processor you're using supports them, it 
would
	be more efficient to use keys to find the superclasses than searching 
each
	time using //CLASS[@NAME=$parentname].
	
	Also below is a full example that I think achieves what you want to 
achieve
	using xsl:apply-templates and modes instead.  I prefer it that way, but 
I
	think it's only a matter of taste.
	
	I may be misunderstanding what you actually want, though - perhaps it 
would
	help if you gave more details about what you're trying to do (i.e. show 
a
	sample input and output) and the XSLT processor you're using.
	
	Cheers,
	
	Jeni
	
	--------
	INPUT: test.xml
	----
	<?xml version="1.0" encoding="UTF-8"?>
	<?xml:stylesheet type="text/xsl" href="test.xsl"?>
	<SCHEMA>
	  <CLASS NAME="animal"/>
	  <CLASS NAME="mammal" SUPERCLASS="animal"/>
	  <CLASS NAME="canine" SUPERCLASS="mammal"/>
	  <CLASS NAME="dog" SUPERCLASS="canine"/>
	  <CLASS NAME="wolf" SUPERCLASS="canine"/>
	  <CLASS NAME="feline" SUPERCLASS="mammal"/>
	  <CLASS NAME="cat" SUPERCLASS="feline"/>
	</SCHEMA>
	--------
	STYLESHEET: test.xsl
	----
	<?xml version="1.0" encoding="UTF-8"?>
	<xsl:stylesheet version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
	
	<xsl:key name="classes" match="CLASS" use="@NAME"/>
	
	<xsl:template match="SCHEMA">
	  <html>
	    <head>
	      <title>A Hierarchy</title>
	    </head>
	    <body>
	      <h1>A Hierarchy</h1>
	      <!-- applies templates in document order -->
	      <xsl:apply-templates/>
	    </body>
	  </html>
	</xsl:template>
	
	<xsl:template match="CLASS">
	  <!-- outputs some information about the class -->
	  <h2><xsl:value-of select="@NAME"/></h2>
	  <p>...more information about the class...</p>
	  <h3>Class Hierarchy</h3>
	  <!-- applies hierarchy template to itself -->
	  <xsl:apply-templates select="." mode="hierarchy"/>
	</xsl:template>
	
	<xsl:template match="CLASS" mode="hierarchy">
	  <!-- applies hierarchy template to the parent of the current class -->
	  <xsl:apply-templates select="key('classes', @SUPERCLASS)" 
mode="hierarchy"/>
	  <!-- outputs details about the current class -->
	  <br data="{@NAME} -- {@SUPERCLASS}">
	    <a href="{@NAME}.html">
	      <xsl:value-of select="@NAME"/>
	    </a>
	  </br>
	</xsl:template>
	
	</xsl:stylesheet>
	--------
	OUTPUT (from Instant SAXON)
	----
	<html xmlns:fo="http://www.w3.org/1999/XSL/Format";>
	   <head>
	      <meta http-equiv="Content-Type" content="text/html; 
charset=utf-8">
	      <title>A Hierarchy</title>
	   </head>
	   <body>
	      <h1>A Hierarchy</h1>
	      	
	      <h2>animal</h2>
	      <p>...more information about the class...</p>
	      <h3>Class Hierarchy</h3><br data="animal -- "><a
	href="animal.html">animal</a>
	      	
	      <h2>mammal</h2>
	      <p>...more information about the class...</p>
	      <h3>Class Hierarchy</h3><br data="animal -- "><a
	href="animal.html">animal</a><br data="mammal -- animal"><a
	href="mammal.html">mammal</a>
	      	
	      <h2>canine</h2>
	      <p>...more information about the class...</p>
	      <h3>Class Hierarchy</h3><br data="animal -- "><a
	href="animal.html">animal</a><br data="mammal -- animal"><a
	href="mammal.html">mammal</a><br data="canine -- mammal"><a
	href="canine.html">canine</a>
	      	
	      <h2>dog</h2>
	      <p>...more information about the class...</p>
	      <h3>Class Hierarchy</h3><br data="animal -- "><a
	href="animal.html">animal</a><br data="mammal -- animal"><a
	href="mammal.html">mammal</a><br data="canine -- mammal"><a
	href="canine.html">canine</a><br data="dog -- canine"><a
	href="dog.html">dog</a>
	      	
	      <h2>wolf</h2>
	      <p>...more information about the class...</p>
	      <h3>Class Hierarchy</h3><br data="animal -- "><a
	href="animal.html">animal</a><br data="mammal -- animal"><a
	href="mammal.html">mammal</a><br data="canine -- mammal"><a
	href="canine.html">canine</a><br data="wolf -- canine"><a
	href="wolf.html">wolf</a>
	      	
	      <h2>feline</h2>
	      <p>...more information about the class...</p>
	      <h3>Class Hierarchy</h3><br data="animal -- "><a
	href="animal.html">animal</a><br data="mammal -- animal"><a
	href="mammal.html">mammal</a><br data="feline -- mammal"><a
	href="feline.html">feline</a>
	      	
	      <h2>cat</h2>
	      <p>...more information about the class...</p>
	      <h3>Class Hierarchy</h3><br data="animal -- "><a
	href="animal.html">animal</a><br data="mammal -- animal"><a
	href="mammal.html">mammal</a><br data="feline -- mammal"><a
	href="feline.html">feline</a><br data="cat -- feline"><a
	href="cat.html">cat</a>
	      
	   </body>
	</html>
	--------
	




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


Current Thread