一个接一个地应用xslt模板以删除空节点

时间:2015-02-12 07:12:58

标签: xml xslt

我写了一个xslt来转换一个xml。但是生成的xml可能有一些空节点,具体取决于源XMl。

现在我想删除那些没有值的空节点。我找到了一些表达式外卡表达式来删除空标签。但我无法将其应用于现有的xslt。

如何在一个工作表中定义多个xsl模板,以便第一个将转换我的源xml,第二个将获取第一个转换的输出并删除空元素或节点

源XML

<?xml-stylesheet type="text/xsl" href="TTT.xsl"?>
<SourceXML>
    <Tag1>Val</Tag1>
    <Tag2></Tag2>
    <Tag3>
        <Tag4></Tag4>
        <Tag5></Tag5>
    </Tag3>
</SourceXML>

XSL

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" /> 
    <xsl:template match="/">
        <TargetXML>
            <TagT1>
                <xsl:value-of select=".//Tag1" />
            </TagT1>
            <TagT2>
                <xsl:value-of select=".//Tag2" />
            </TagT2>
            <TagT3>
                <TagT4>
                    <xsl:value-of select=".//Tag3/Tag4" />
                </TagT4>
                <TagT5>
                    <xsl:value-of select=".//Tag3/Tag5" />
                </TagT5>
            </TagT3>
        </TargetXML>
    </xsl:template>
</xsl:stylesheet>

输出

<TargetXML>
    <TagT1>Val</TagT1>
    <TagT2></TagT2>
    <TagT3>
        <TagT4></TagT4>
        <TagT5></TagT5>
    </TagT3>
</TargetXML>

但我希望得到一个像这样的输出

<TargetXML>
    <TagT1>Val</TagT1>
</TargetXML>

任何人都可以解释如何实现相同的

1 个答案:

答案 0 :(得分:2)

如果您愿意,可以将第一遍的结果存储在变量中,然后将更多模板应用于结果,仅传递具有实际值的节点:

XSLT 1.0

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- first pass -->
<xsl:template match="/" mode="first-pass">
    <TargetXML>
        <TagT1>
            <xsl:value-of select=".//Tag1" />
        </TagT1>
        <TagT2>
            <xsl:value-of select=".//Tag2" />
        </TagT2>
        <TagT3>
            <TagT4>
                <xsl:value-of select=".//Tag3/Tag4" />
            </TagT4>
            <TagT5>
                <xsl:value-of select=".//Tag3/Tag5" />
            </TagT5>
        </TagT3>
    </TargetXML>
</xsl:template>

<xsl:template match="/">    
    <!-- apply first pass -->
    <xsl:variable name="first-pass">
        <xsl:apply-templates select="." mode="first-pass"/>
    </xsl:variable>
    <!-- final output -->
    <xsl:apply-templates select="exsl:node-set($first-pass)/*"/>
</xsl:template>

<xsl:template match="*[normalize-space(descendant::text()) or descendant-or-self::*/@*[string()]]">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="@*[string()]">
    <xsl:copy/>
</xsl:template>

</xsl:stylesheet>