如果子节点为空,则移除父节点

Remove parent node if child node is empty

我正在尝试使用 xslt 转换给定的 XML。需要注意的是,如果给定的子节点不存在,我将不得不删除父节点。我确实做了一些模板匹配,但我被卡住了。任何帮助将不胜感激。

输入xml:

<?xml version="1.0" encoding="UTF-8"?>
<main>
     <item>
        <value>
           <item>
              <value>ABC</value>
              <key>test1</key>
           </item>
           <item>
              <value>XYZ</value>
              <key>test2</key>
           </item>
               <item>
              <value></value>
              <key>test3</key>
           </item>
        </value>
     </item>
     <item>
        <value />
        <key>test4</key>
     </item>
     <item>
        <value>PQR</value>
        <key>test5</key>
     </item>
</main>

预期输出:

<?xml version="1.0" encoding="UTF-8"?>
<main>
     <item>
        <value>
           <item>
              <value>ABC</value>
              <key>test1</key>
           </item>
           <item>
              <value>XYZ</value>
              <key>test2</key>
           </item>
        </value>
     </item>
     <item>
        <value>PQR</value>
        <key>test5</key>
     </item>
</main>

问题是如果我使用模板匹配,例如

<xsl:template match="item[not(value)]"/>deleting the parent node if child node is not present in xml using xslt 中所述,然后它会完全删除所有内容,因为 main/item/value 也是空的。

我需要的是如果元素为空则移除但仅当元素没有子元素时才移除。

我认为您想删除它根本没有子元素的元素(无论这些子元素是元素还是文本节点)。尝试插入此模板:

<xsl:template match="item">
    <xsl:if test="exists(value/node())">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:if>
</xsl:template>

您应该首先从 XSLT 标识模板开始

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

那么,您所需要的只是一个匹配 item 元素的模板,其中所有后代叶 value 元素都是空的。

 <xsl:template match="item[not(descendant::value[not(*)][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="item[not(descendant::value[not(*)][normalize-space()])]" />

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

如果我没看错的话,你想做的是:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="item[not(value[node()])]"/>

</xsl:stylesheet>

这将删除所有 item 没有 value 子级的 一些 内容。