【问题标题】:XSLT how to remove empty elements and their parent nodesXSLT 如何删除空元素及其父节点
【发布时间】:2015-09-15 07:28:54
【问题描述】:

我有这个输入 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(.))]"/>

【问题讨论】:

    标签: xslt


    【解决方案1】:

    假设您有格式良好的 XML,并且命名空间 URI 是为 mods 前缀定义的,那么通常最好从使用 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>
    

    【讨论】:

    • 顺便说一句,descendant::text()[normalize-space()] 在语义上不等同于 .[normalize-space()]
    • 是的,你是对的。模板匹配可以简化为&lt;xsl:template match="*[not(.[normalize-space()])]" /&gt;。顺便说一句,“它的”是正确的;)
    猜你喜欢
    • 2022-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多