XSLT如何删除空元素及其父节点

时间:2015-09-15 07:28:55

标签: xslt

我有这个输入XML:

<mods:relatedItem type="constituent">
    <mods:name type="corporate">
        <mods:namePart>Financijer projekta</mods:namePart>
    </mods:name>
    <mods:name type="corporate">
        <mods:namePart/>
    </mods:name>
    </mods:name>
        <mods:namePart/>
    </mods:name>
    </mods:name>
        <mods:namePart>Program financiranja</mods:namePart>
    </mods:name>
    <mods:identifier>Šifra projekta</mods:identifier>
    <mods:identifier/> 
    <mods:titleInfo>
        <mods:title>Naziv projekta</mods:title>
    </mods:titleInfo>
    <mods:titleInfo>
        <mods:title/>
    </mods:titleInfo>
    <mods:titleInfo type="alternative">
        <mods:title>Akronim projekta</mods:title>
    </mods:titleInfo>
    <mods:titleInfo type="alternative">
        <mods:title/>
    </mods:titleInfo>
</mods:relatedItem>

我希望摆脱所有空的元素及其父节点。

最终的XML应如下所示:

<mods:relatedItem type="constituent">
    <mods:name type="corporate">
        <mods:namePart>Financijer projekta</mods:namePart>
        </mods:name>
        </mods:name>
        <mods:namePart>Program financiranja</mods:namePart>
    </mods:name>
    <mods:identifier>Šifra projekta</mods:identifier>
    <mods:titleInfo>
        <mods:title>Naziv projekta</mods:title>
    </mods:titleInfo>
    <mods:titleInfo type="alternative">
        <mods:title>Akronim projekta</mods:title>
    </mods:titleInfo>
</mods:relatedItem>

我尝试进行转换,但从未让删除空元素部分工作

   <xsl:template match="/">
    <xsl:apply-templates select="@*|node()"/>
    </xsl:template>
    <xsl:template match="/mods:mods/mods:relatedItem/mods:name[@type]/mods:namePart[not(string(.))]"/>
    <xsl:template match="/mods:mods/mods:relatedItem/mods:name[not(@type)]/mods:namePart[not(string(.))]"/>
    <xsl:template match="/mods:mods/mods:relatedItem/mods:identifier[not(string(.))]"/>
    <xsl:template match="/mods:mods/mods:relatedItem/mods:titleInfo[not(@type)]/mods:title[not(string(.))]"/>
    <xsl:template match="/mods:mods/mods:relatedItem/mods:titleInfo[@type]/mods:title[not(string(.))]"/>

1 个答案:

答案 0 :(得分:3)

假设您有格式良好的XML,并且为mods前缀定义了名称空间URI,那么通常最好先使用Identity Template

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

就其本身而言,它会按原样复制所有节点,这意味着您只需要为要删除的节点编写模板。理想情况下,您希望以通用方式执行此操作,因此此模板应该

 <xsl:template match="*[not(descendant::text()[normalize-space()])]" />

试试这个XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes" />

    <xsl:template match="*[not(descendant::text()[normalize-space()])]" />

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>