我有一些复杂的XSLT 2.0转换。我试图找出是否有通用的方法来确保不输出空标签。所以......从概念上讲,处理的最后阶段会递归删除所有空标记。我知道这可以通过一个单独的XSLT来完成,它除了过滤掉空标签之外什么都不做,但是我需要将它们全部打包在一起。
答案 0 :(得分:8)
此XSLT 2.0转换说明了如何完成多遍(在本例中为2遍)处理:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*" mode="#all">
<xsl:copy>
<xsl:apply-templates select="node()|@*" mode="#current"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:variable name="vPass1">
<xsl:apply-templates/>
</xsl:variable>
<xsl:apply-templates select="$vPass1/*" mode="non-empty"/>
</xsl:template>
<xsl:template match="text()[xs:integer(.) mod 2 eq 0]"/>
<xsl:template match="*[not(node())]" mode="non-empty"/>
</xsl:stylesheet>
应用于此XML文档时:
<nums>
<num>01</num>
<num>02</num>
<num>03</num>
<num>04</num>
<num>05</num>
<num>06</num>
<num>07</num>
<num>08</num>
<num>09</num>
<num>10</num>
</nums>
它在第一遍中创建一个结果文档(在$vPass1
变量中捕获),其中所有内容均为整数的<num>
元素都被剥离其内容并为空。然后,在以特定模式应用的第二遍中,移除所有空元素。
转化的结果是:
<nums>
<num>01</num>
<num>03</num>
<num>05</num>
<num>07</num>
<num>09</num>
</nums>
请注意使用模式,以及特殊模式#all
和#current
。
更新: OP现在希望在评论中“递归地”删除“没有非空后代的所有节点”。
这可以使用没有显式递归更简单地实现。只需改变:
<xsl:template match="*[not(node())]" mode="non-empty"/>
为:
<xsl:template match="*[not(descendant::text())]" mode="non-empty"/>