[xsl] Recursive evaluation of expressions

Subject: [xsl] Recursive evaluation of expressions
From: "Rowan Sylvester-Bradley" <rowan@xxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 19 Dec 2009 01:18:10 -0000
I'm still struggling to get this working. I need to be able to evaluate
XPath expressions in my input XML document. This works OK, but I also need
to be able to refer in an XPath expression to an element that contains
another expression, and to pick up the result of evaluating the second
expression, not just the text of the expression.
Here's a sample input document:
<items>
   <item>
      <id>a</id>
      <caption>Sandwich Meal</caption>
      <item>
         <id>a1</id>
         <description>White roll</description>
         <caption><eval>concat($p1/../caption, ' ',
$p1/description)</eval></caption>
         <item>
            <id>a1a</id>
            <description>Chicken</description>
            <caption><eval>concat($p1/../caption, ' ',
$p1/description)</eval></caption>
         </item>
         <item>
            <id>a1b</id>
            <description>Ham</description>
            <caption><eval>concat($p1/../caption, ' ',
$p1/description)</eval></caption>
         </item>
      </item> 
   </item>    
</items>                 

And here's a simplified version of my stylesheet:
<xsl:stylesheet version="2.0" 
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
   xmlns:xs="http://www.w3.org/2001/XMLSchema";
   xmlns:saxon="http://saxon.sf.net/";
   exclude-result-prefixes="xs saxon">

   <xsl:strip-space elements="*"/>
   <xsl:output indent="yes"/>
   
   <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
   </xsl:template>  
   
   <xsl:template match="item">
      <item>
         <xsl:apply-templates>
            <xsl:with-param name="source" select="." tunnel="yes"/>
         </xsl:apply-templates>   
      </item>
   </xsl:template>
   
   <xsl:template match="eval">
      <xsl:param name="source" tunnel="yes"/>
      <xsl:value-of select="saxon:eval(saxon:expression(.), $source)"/>
   </xsl:template>   

</xsl:stylesheet>  

This produces the following:
<?xml version="1.0" encoding="UTF-8"?>
<items>
   <item>
      <id>a</id>
      <caption>Sandwich Meal</caption>
      <item>
         <id>a1</id>
         <description>White roll</description>
         <caption>Sandwich Meal White roll</caption>
         <item>
            <id>a1a</id>
            <description>Chicken</description>
            <caption>concat($p1/../caption, ' ', $p1/description)
Chicken</caption>
         </item>
         <item>
            <id>a1b</id>
            <description>Ham</description>
            <caption>concat($p1/../caption, ' ', $p1/description)
Ham</caption>
         </item>
      </item>
   </item>
</items>

What I want instead of              
            <caption>concat($p1/../caption, ' ', $p1/description)
Chicken</caption>
is
            <caption>Sandwich Meal White roll Chicken</caption>

How can I get it to do this?

Many thanks - Rowan

Current Thread