I am using XSLT to convert a very large XML document into (X)HTML. For some of the tags I am converting them to a
The natural/idiomatic/failsafe solution would be:
<div class="book" id="book-{generate-id()}">
It's not incrementing, but it's guaranteed to be unique. And it's going to produce HTML-valid ID strings (name tokens).
EDIT: If it must be incrementing, do something like the following:
<!-- in the calling template… -->
<xsl:apply-templates select="bookcoll/book[xpath to filter them if necessary]" />
<!-- …later -->
<xsl:template match="bookcoll/book">
<div class="book" id="book-{position()}">
<xsl:apply-templates/>
</div>
</xsl:template>
You can use format-number()
to adapt the output of position()
to your needs.
position()
will return the node position relative to the "batch" that is currently being processed. With an explicit call to <xsl:apply-templates>
you make sure that they are numbered the way you want.
Look into the position() function.
As suggested several times before, you need position()
, but you have to iterate over the items using xsl:for-each
:
<xsl:template match="bookcoll">
<xsl:for-each select="book">
<div class="book" id="book-{position()}">
<xsl:apply-templates/>
</div>
</xsl:for-each>
</xsl:template>
This will produce something like:
<div class="book" id="book-1">book1</div>
<div class="book" id="book-2">book2</div>
<div class="book" id="book-3">book3</div>
for
<bookcoll>
<book>book1</book>
<book>book2</book>
<book>book3</book>
</bookcoll>
You can add callouts to static methods on Java classes to your transforms... it works but there are some downsides like 1) Now your transform is tied to some Java code and is harder to test/debug in external tools like Oxygen (although there are some ways to mitigate this) 2) You have to maintain state as statics or perhaps thread locals, which can introduce all kinds of problems (synchronization issues, questions about resetting if you are doing this multiple times, Etc)