如何使用递增的计数器在XSLT中提供唯一的ID?

时间:2009-11-10 18:34:09

标签: java xslt xhtml

我正在使用XSLT将非常大的XML文档转换为(X)HTML。对于某些代码,我将它们转换为<div>。我希望能够为这些标记创建唯一的id,使用递增的整数形成唯一id的一部分。

我使用的规则的一个例子是:

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

这个XSLT模板运行良好。我现在想要的是标签:

<div class="book">;  

成为:

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

理想情况下,计数器将从1开始,而不是0。

我不知道它是否有很大的不同,我使用Java包javax.xml.parsers和javax.xml.transform来执行实际的转换。我是一个XSLT菜鸟,所以如果有任何我错过的相关信息,请告诉我。

如何在XSLT中实现这一目标?

4 个答案:

答案 0 :(得分:7)

自然/惯用/故障安全解决方案将是:

<div class="book" id="book-{generate-id()}">

它没有递增,但它保证是独一无二的。它将生成HTML有效的ID字符串(name tokens)。

编辑:如果必须递增,请执行以下操作:

<!-- 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>

您可以使用format-number()根据您的需要调整position()的输出。

position()将返回相对于当前正在处理的“批处理”的节点位置。通过显式调用<xsl:apply-templates>,您可以确保按照您想要的方式编号。

答案 1 :(得分:4)

根据之前的建议,您需要position(),但必须使用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>

这会产生类似的东西:

<div class="book" id="book-1">book1</div>
<div class="book" id="book-2">book2</div>
<div class="book" id="book-3">book3</div>

<bookcoll>
    <book>book1</book>
    <book>book2</book>
    <book>book3</book>
</bookcoll>

答案 2 :(得分:0)

您可以将Java类上的静态方法的标注添加到转换中...它可以工作但是有一些缺点 1)现在你的转换与一些Java代码绑定,并且在像Oxygen这样的外部工具中更难测试/调试(尽管有一些方法可以缓解这种情况) 2)您必须将状态维持为静态或线程本地,这可能会引入各种问题(同步问题,如果您多次执行此操作有关重置的问题,等等)

答案 3 :(得分:0)

查看position()函数。