How to use an incremented counter to provide a uni

2019-02-25 08:29发布

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 <div>. I would like to be able to create a unique id for these tags, using an incremented integer to form part of the unique id.

An example of the rule I am using is:

<xsl:template match="bookcoll/book">
    <div class="book">
        <xsl:apply-templates/>
    </div>
</xsl:template>

This XSLT template is working nicely. What I would now like to have is the tag:

<div class="book">;  

becoming:

<div class="book" id="book-[COUNTER-VALUE]">  

Ideally the counter would start from 1, not 0.

I don't know if it makes much difference, I am using the Java packages javax.xml.parsers and javax.xml.transform to perform the actual transformation. I am a bit of an XSLT noob, so if there's any pertinent information I've missed please let me know.

How could this be achieved in XSLT?

标签: java xslt xhtml
4条回答
爷、活的狠高调
2楼-- · 2019-02-25 09:02

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.

查看更多
狗以群分
3楼-- · 2019-02-25 09:04

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)

查看更多
我想做一个坏孩纸
4楼-- · 2019-02-25 09:14

Look into the position() function.

查看更多
smile是对你的礼貌
5楼-- · 2019-02-25 09:27

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>
查看更多
登录 后发表回答