Subject: [xsl] Recursive evaluation of elements From: "Rowan Sylvester-Bradley" <rowan@xxxxxxxxxxxxxxxxxxxxx> Date: Sat, 12 Dec 2009 00:08:18 -0000 |
I have a stylesheet that now successfully expands sub-trees using multiple "rows" from "tables" (the rows and tables are all part of the input XML file). I can have one expand inside another giving a two-dimensional expansion. Another feature of the system that I'm building is that in the contents of an element of the input file I can include an XPath expression surrounded by braces. My stylesheet recognises the braces using analyze-string, and evaluates the expression within them using saxon:eval. Parameters $p1 and $p2 allow me to refer in these expressions to elements in the source tree and in the current table row. This all works fine unless I have an expression in an inner expansion that refers to the result of an expression in an outer expansion. In this case what I need to happen is that the inner expression uses as its parameter the result of the outer expression. What actually happens is the inner expression uses the literal outer expression, without evaluation. I can see that this is because the $source variable is set to a subtree from the source document. But I can't see how to get it to do what I want. I tried putting an apply-templates in several places, and immediately got a stack overflow error, even on a small test file. 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:key name="t" match="table" use="id"/> <xsl:template match="*" mode="#all"> <xsl:copy> <xsl:apply-templates/> </xsl:copy> </xsl:template> <xsl:template match="tables" mode="#all"/> <xsl:template match="item[expand]" mode="#all"> <xsl:variable name="here" select="."/> <xsl:for-each select="key('t',expand)/row"> <item> <!-- <xsl:apply-templates select="$here/(* except item),*,$here/item" mode="expand"> --> <xsl:apply-templates select="$here/*" mode="expand"> <xsl:with-param name="source" select="$here" tunnel="yes"/> <xsl:with-param name="tablerow" select="." tunnel="yes"/> </xsl:apply-templates> </item> </xsl:for-each> </xsl:template> <xsl:template match="expand" mode="expand"/> <xsl:template match="text()" priority="2" mode="#all"> <xsl:param name="source" tunnel="yes"/> <xsl:param name="tablerow" tunnel="yes"/> <xsl:analyze-string select="." regex="\{{([^\}}]+)\}}"> <xsl:matching-substring> <xsl:value-of select="saxon:eval(saxon:expression(regex-group(1)), $tablerow, $source)"/> </xsl:matching-substring> <xsl:non-matching-substring> <xsl:value-of select="."/> </xsl:non-matching-substring> </xsl:analyze-string> </xsl:template> </xsl:stylesheet> And here's a sample input file: <root> <items> <item> <id>a</id> <type>lineitem</type> <expand>Table1</expand> <name>{concat('Item A', ' result')} of expression</name> <description>{$p1/name}</description> <price>{$p1/price * 2}</price> </item> <item> <id>b</id> <type>lineitem</type> <expand>Table1</expand> <name>Item B</name> <price>{$p1/price * 2}</price> <item> <id>b1</id> <type>delivery</type> <expand>Table2</expand> <name>{concat($p2/../name, ' delivered by ', $p1/name)}</name> <price>{$p1/price * 3}</price> </item> </item> <item> <id>c</id> <type>lineitem</type> <expand>Table1</expand> <name>Item C ({$p1/name})</name> <price>{$p1/price * 2}</price> <item> <id>c1</id> <type>delivery</type> <expand>Table2</expand> <name>{concat($p2/../name, ' delivered by ', $p1/name)}</name> <!-- <price>{$p2/../price + $p1/price}</price> --> </item> </item> </items> <tables> <table> <id>Table1</id> <row> <name>A nasty cheap one</name> <price>0.49</price> </row> <row> <name>This one's gold plated</name> <price>9.99</price> </row> </table> <table> <id>Table2</id> <row> <name>Second Class</name> <price>0.25</price> </row> <row> <name>First Class</name> <price>0.50</price> </row> <row> <name>Express</name> <price>1.00</price> </row> </table> </tables> </root> Items 'a' and 'b' expand fine, and the braces expressions evaluate correctly. Item 'c' expands OK, but the value of the name element in item c1 is: <name>Item C ({$p1/name}) delivered by Second Class</name> What I need is: <name>Item C (A nasty cheap one) delivered by Second Class</name> Can anyone suggest how to do this? Many thanks - Rowan
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] RE: Using divide-and-conq, Dimitre Novatchev | Thread | Re: [xsl] Recursive evaluation of e, Florent Georges |
RE: [xsl] Using divide-and-conquer , Michael Kay | Date | Re: [xsl] Using divide-and-conquer , Andrew Welch |
Month |