Subject: [xsl] enumerating things (global counter) From: Andreas Leitner <nozone@xxxxxxxxxxxxxx> Date: 17 Apr 2002 18:03:41 +0200 |
Hi, I got a problem, which I cannot seem to solve. I tried and tried, searched google, but did not find a satisfactory answere. Here is the problem: I am trying to create a Stylesheet that transforms an extended DocBook file back to standard DocBook. The extension would be a <requirement> element, that can occure inside any element that would allow a docbook section. Such a 'requirement' element (its for creating a user requirements document) would translate like the following example shows: <chapter> <title> ... </title> <section> <title>Requirements</title> <requirement name="foo"> <para> ... </para> </requirement> <requirement name="bar"> <para> ... </para> </requirement> <requirement name="baz"> <para> ... </para> <requirement name="nested_baz"> <para> ... </para> </requirement> </requirement> </section> </chapter> translates to: <chapter> <title> ... </title> <section> <title>Requirements</title> <section> <title>REQ1: foo</title> <para> ... </para> </section> <section> <title>REQ2: bar</title> <para> ... </para> </section> <section> <title>REQ3: baz</title> <para> ... </para> <section> <title>REQ4: nested_baz</title> <para> ... </para> </section> </section> </section> </chapter> What I need is to give each requirement title an ascendending number (in document order), but I have no idea how to do that. Ideally my Stylesheet would not know about docbook grammar at all. I tried a lot, but I think my best guess was: <xsl:stylesheet> <xsl:template match="*"> <xsl:element name="{name()}" namespace="{namespace-uri()}"> <xsl:copy-of select="namespace::*"/> <xsl:copy-of select="@*"/> <xsl:apply-templates /> </xsl:element> </xsl:template> <xsl:template match="requirement"> <xsl:element name="section"> <xsl:element name="title"> REQ <xsl:value-of select="count(preceding::requirement) + 1"/>: <xsl:value-of select="@name"/> </xsl:element> <xsl:apply-templates/> </xsl:element> </xsl:template> </xsl:stylesheet> But that does not take into account all preceding requirements. Another guess was to use for-each in the following way: <xsl:template match="requirement"> <xsl:element name="section"> <xsl:element name="title"> REQ <xsl:for-each select="///requirement"> <xsl:if test=".=current()"> <xsl:value-of select="position()"/> </xsl:if> </xsl:for-each> <xsl:value-of select="@name"/> </xsl:element> <xsl:apply-templates/> </xsl:element> </xsl:template> But 'position()' seems to return always the same number, no idea why. Does anybody know how to solve this problem? Basically it's the same thing as if one would be enummerating figures in a latex document. In latex one would have global counters, but XSLT cannot have those, since it needs to be side-effect free. In a conventional functional language I would introduce a global state via returning the global state from one function and passing it to the next as argument, but templates do not have a return value, right? -- example of how to use global state in languages like sml state1 = foo (initial_state, ...) state2 = bar (state1, ...) state3 = baz (state2, ...) ... --- I am quite sure this problem has been already solved elsewhere, since it looks rather common to me. many thanks in advance, Andreas XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: FW: [xsl] XML transformation us, David Carlisle | Thread | Re: [xsl] enumerating things (globa, Jeni Tennison |
RE: [xsl] <MsSinceMidnight1Jan1970>, Chris Bayes | Date | RE: [xsl] xsl sorting (Follow-up qu, Greg Faron |
Month |