Re: [xsl] Getting variable yet most immediate parentNode

Subject: Re: [xsl] Getting variable yet most immediate parentNode
From: Abel Braaksma <>
Date: Thu, 27 Sep 2007 22:40:56 +0200
Steve wrote:
Problem: given the variable relationship between the <answer> nodes
being matched and their parent <section>, how to reliably amtch the
correct section @name?

				<xsl:when test="../../../answers">
					<xsl:apply-templates select="../../../answers" >
						<xsl:with-param name="qKey" select="@key" />

Hi Steve,

I'm sorry to not have looked into your problemm as I lack the time at the moment, but consider the structure above, you have lots of them. Whenever you find yourself writing something like that, think again and start refactoring right away to make your code easier to read *and* remove redundancy. The redundancy in the above code is the "if nodex then apply nodex", which can simple be rewritten as "apply nodex": applying templates to something that is not there is applying something to nothing is nothing. Hence: the if-statement is redundant.

Rewrite the above as (totally without the xsl:choose!):

<xsl:apply-templates select="../../../answers" />

In addition, you have three ways of writing 'answers': ,../answers, ../../answers and ../../../answers. I am sure that while you were writing it you were thinking something like "it must be possible to achieve this effect more easily"... There are several ways to code around the path-depth problem, but the easiest is probably to leave the path out completely, if you are certain that "answer" elements are what they are at any level: answer elements (and even if you do find later that you have different treatment for different answer-elements, you will simply add a new rule):

I ususally advise against it, but this is a good place to code:

<xsl:apply-templates select=".//answers" />


<xsl:template match="answers">
  .... your logic here

That's all you need! Much easier than the unmaintainable and ununderstandably long xsl:choose, no?
Same with the following bit. You wrote:

   <xsl:when test="@name">
       <xsl:value-of select="@name"/>
   <xsl:otherwise><xsl:value-of select="." /></xsl:otherwise>

This statement is exactly equal to (if you use xslt 2.0):

<xsl:value-of select="(@name, .)[1]" />

But in general is better written out in rules, which are easier to follow:

<xsl:apply-templates select="@name | ." />

<xsl:template match="option/@name"><xsl:value-of select="." /></..
<xsl:template match="option[not(@name)]"><xsl:value-of select="." /></...

Later in your stylesheet you go on and on trying to understand the logic of the difficult input xml and feed it to the xslt processor. But why don't you turn it around? Define the rules in matching templates and you will see that your stylesheet becomes both easy to write and easy to maintain / adjust.

A good introduction on how to understand the template matching principles are Jeni Tennison's books, she has several, but her intro's on XSLT 1.0 and XSLT 2.0 (two separate books) are excellent (biases opinion from me).

Have fun with coding, make it yourself easy! ;)

-- Abel Braaksma --

Current Thread