我正在使用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中实现这一目标?
答案 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()函数。