RE: [xsl] enumerating things (global counter)

Subject: RE: [xsl] enumerating things (global counter)
From: "Michael Earls" <michael@xxxxxxxxxx>
Date: Wed, 17 Apr 2002 21:20:46 -0400
I had to do something similar today, try this (this assumes that your
sample is accurate):

<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:with-param name="parent_position">
			<xsl:value-of select="position()"/>
		</xsl:with-param>
	</xsl:apply-templates>
    </xsl:element>
  </xsl:template>

<xsl:template match="requirement">
	<xsl:param name="parent_position"/>
    <xsl:element name="section">
      <xsl:element name="title">
        REQ
        <xsl:value-of select="$parent_position"/>:
        <xsl:value-of select="@name"/>
      </xsl:element>
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

Just a thought.  Like I said, I had to do something similar, though it
may not be the result you are looking for.

Michael Earls

-----Original Message-----
From: owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx
[mailto:owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx] On Behalf Of Andreas
Leitner
Sent: Wednesday, April 17, 2002 12:04 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: [xsl] enumerating things (global counter)


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


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


Current Thread