我有一个带有<section>
标签的文档格式,可以无限嵌套。每个部分都包含段落和表格等内容,但新部分的第一个元素可能是任何部分,包括另一部分。
<doc>
<section name="one">
<p> Some text about <i>this</i> section.</p>
<section name="one.one">
<section name="one.one.one">
<p>Other text</p>
</section>
</section>
</section>
</doc>
我将文档格式转换为markdown。似乎应用大多数标签的自然方式是使用如下结构:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="doc|p">
<xsl:apply-templates select="* | text()"/>
</xsl:template>
<xsl:template match="i">
<xsl:text>_</xsl:text>
<xsl:apply-templates select="* | text()"/>
<xsl:text>_</xsl:text>
</xsl:template>
</xsl:stylesheet>
但是,对于<section>
标记,我需要跟踪嵌套深度以构建节名称。似乎这样做的自然方式是使用<xsl:call-template>
和<xsl:param>
。
<xsl:template match="section">
<xsl:param name="depth" select="1"/>
<!-- do stuff to write the section name -->
<xsl:apply-templates select="* | text()"/>
</xsl>
我遇到的问题是需要使用<xsl:call-template>
而不是<xsl:apply-templates>
来触发,以便增加参数。
<xsl:call-template name="section">
<xsl:with-param name="depth" select="$depth+1"/>
</xsl:call-template>
我无法为apply-templates
提供参数,但我也无法使用递归section
启动doc
(或call-template
)模板,因为新的部分可能不是第一个标签。
有没有办法解决这个问题,让我使用call-template
,但只保留xslt通常只使用简单apply-templates
标记的标记顺序?
答案 0 :(得分:2)
以下是使用xsl:number
(level="multiple"
)确定深度的示例。这样会为您提供类似1.1.1.
(第三级)的内容,但您可以将.
翻译为#
(并将数字翻译为空)。
XML输入
<doc>
<section name="one">
<p> Some text about <i>this</i> section.</p>
<section name="one.one">
<section name="one.one.one">
<p>Other text</p>
</section>
</section>
</section>
</doc>
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="chars" select="'.0123456789'"/>
<xsl:template match="i">
<xsl:value-of select="concat('_',.,'_')"/>
</xsl:template>
<xsl:template match="p">
<xsl:apply-templates/>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="section">
<xsl:variable name="depth">
<xsl:number level="multiple" format="1."/>
</xsl:variable>
<xsl:value-of select="translate($depth,$chars,'#')"/>
<xsl:value-of select="concat(@name,'
')"/>
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
<强>输出强>
#one
Some text about _this_ section.
##one.one
###one.one.one
Other text
修改强>
这是另一种计算像迈克尔凯建议的祖先或自我的方式(呃!)......
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="i">
<xsl:value-of select="concat('_',.,'_')"/>
</xsl:template>
<xsl:template match="p">
<xsl:apply-templates/>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="section">
<xsl:for-each select="ancestor-or-self::section">#</xsl:for-each>
<xsl:value-of select="concat(@name,'
')"/>
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
首先,您可以使用apply-templates传递params,就像使用call-template一样简单:apply-templates允许使用xsl:with-param子元素。
其次,您不需要参数来确定嵌套的深度,因为您可以使用向上导航的XPath表达式,例如count(ancestor::section)
。