2010-07-07 42 views
8

我有一些复杂的XSLT 2.0转换。我试图找出是否有通用的方法来确保不输出空标签。所以......从概念上讲,递归处理的最后阶段是删除所有空标签。我知道这可以通过一个单独的XSLT来完成,它不做任何事情,但是会过滤掉空标签,但我需要将它们全部封装在一起。两阶段处理:不要输出阶段1 XSLT 2.0处理中的空标记

+0

很好的问题(+1)。查看我的答案以获得详细解决方案。 – 2010-07-08 01:06:35

回答

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>元素r被删除了内容并且是空的。然后,在第二遍中,以特定模式应用,所有空元素都被删除。

转换的结果是

<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"/> 
+0

这回答了整个问题,但有一个特定的部分它未命中 - 递归地删除所有空标签...所以我只需要将“* [not(node())]”更改为适当的表达式,这意味着所有没有非空后裔的节点。 – mentics 2010-07-08 09:01:39

+0

@taotree下一次更好地陈述你的问题。 :)我认为最好将这个新要求作为一个单独的问题 - 这也是一个很好的问题。您可以使用空模板的匹配模式:'* [not(descendant :: text())]' – 2010-07-08 12:41:08

+0

@taotree更新了答案以反映您的新需求... :) – 2010-07-08 12:49:47