我有这个XSLT 2.0模板:
<xsl:template match="footnote">
<xsl:variable name = "string" select="./text()"/>
<xsl:variable name = "bool">
<xsl:choose>
<xsl:when test="$string = preceding::footnote/text()">
<xsl:text>false</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>true</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:if test="$bool = 'true'">
<xsl:variable name="footnoteCount">
<xsl:call-template name="getItemNumber">
<xsl:with-param name="node" select="."/>
</xsl:call-template>
</xsl:variable>
<!-- DO XSL-FO TRANSFORMATION STUFF-->
</xsl:if>
<xsl:if test="$bool = 'false'">
<xsl:variable name = "footnoteCount">
<xsl:if test="$string = preceding::footnote/text()">
<xsl:value-of select="preceding::footnote/$footnoteCount"/>
</xsl:if>
</xsl:variable>
<!--DO XSL-FO TRANSFORMATION STUFF-->
</xsl:if>
</xsl:template>
编辑样本XML。我想改变这个:
<footnote>Foo bar</footnote>
<footnote>Bar foo</footnote>
<footnote>Foo bar</footnote>
<footnote>Foo bar</footnote>
<footnote>Bar</footnote>
<footnote>Foo</footnote>
进入这个:
<footnote>Foo bar</footnote>
<footnote>Bar foo</footnote>
<footnote>Bar</footnote>
<footnote>Foo</footnote
然后使用XSL-FO对其进行样式化。这种样式的目的是主体中的文本将有一个带编号的引用(由$footnotecount
表示)到脚注,然后在页面底部呈现。我需要转换文档,以便重复的脚注仅呈现一次,并且每个副本的数字引用($footnoteCount
)都相同。
所以我试图用这个模板做的是:
这就是脚本已经存在的情况,我遇到了麻烦。我不知道如何从以前的特定节点获取$ footnoteCount变量,这取决于节点是否满足某个条件(其文本是否与当前节点中的$ string变量相同)。由于$ footnoteCount变量只是有条件地存在(即使在实践中它总是存在,因为$ bool必须是true或false),这变得更加困难。
有没有人建议在这做什么?
答案 0 :(得分:1)
这看起来像是分组问题,在XSLT2.0中,您可以使用 xsl:for-each-group 元素来获取不同的元素
<xsl:for-each-group select="footnote" group-by=".">
我认为你需要一种不同的方法来编号。首先,您可以创建一个变量来保存脚注描述及其索引的“查找”
<xsl:variable name="footnotes">
<xsl:for-each-group select="//footnote" group-by=".">
<footnote id="{position()}">
<xsl:value-of select="."/>
</footnote>
</xsl:for-each-group>
</xsl:variable>
这意味着脚注变量包含以下元素
<footnote id="1">Foo bar</footnote>
<footnote id="2">Bar foo</footnote>
<footnote id="3">Bar</footnote>
<footnote id="4">Foo</footnote>
然后,要用数字引用替换现有的脚注元素,您将拥有这样的模板
<xsl:template match="footnote">
<footnote>
<xsl:value-of select="$footnotes/footnote[. = current()]/@id"/>
</footnote>
</xsl:template>
尝试以下XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="footnotes">
<xsl:for-each-group select="//footnote" group-by=".">
<footnote id="{position()}">
<xsl:value-of select="."/>
</footnote>
</xsl:for-each-group>
</xsl:variable>
<xsl:template match="/*">
<xsl:apply-templates select="footnote"/>
Footnotes
<xsl:copy-of select="$footnotes"/>
</xsl:template>
<xsl:template match="footnote">
<footnote>
<xsl:value-of select="$footnotes/footnote[. = current()]/@id"/>
</footnote>
</xsl:template>
</xsl:stylesheet>
当应用于您的示例XML(假设根元素)时,输出以下内容
<footnote>1</footnote>
<footnote>2</footnote>
<footnote>1</footnote>
<footnote>1</footnote>
<footnote>3</footnote>
<footnote>4</footnote>
Footnotes
<footnote id="1">Foo bar</footnote>
<footnote id="2">Bar foo</footnote>
<footnote id="3">Bar</footnote>
<footnote id="4">Foo</footnote>
答案 1 :(得分:1)
除了未使用xsl:for-each-group之外,您的代码还有许多其他问题。例如,采取这个:
<xsl:variable name = "bool">
<xsl:choose>
<xsl:when test="$string = preceding::footnote/text()">
<xsl:text>false</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>true</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
您可以将其写为
<xsl:variable name="bool" as="xs:boolean()"
select="$string = preceding::footnote"/>
然后你这样做:
<xsl:if test="$bool = 'true'">
<xsl:variable name="footnoteCount">
<xsl:call-template name="getItemNumber">
<xsl:with-param name="node" select="."/>
</xsl:call-template>
</xsl:variable>
</xsl:if>
这完全没用:变量声明后就会超出范围,因此永远不会被引用。
你需要做一些关于XSLT的背景阅读,还有很多你还没有掌握的想法。