Xslt 如果子节点为空,则删除父节点

Xslt 如果子节点为空,则删除父节点,xslt,xslt-2.0,Xslt,Xslt 2.0,我正在尝试使用xslt转换给定的XML。需要注意的是,如果给定的子节点不存在,我将不得不删除父节点。我确实做了一些模板匹配,但我被卡住了。任何帮助都将不胜感激 输入xml: <?xml version="1.0" encoding="UTF-8"?> <main> <item> <value> <item> <value>ABC</value&

我正在尝试使用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>

基础知识
测试1
XYZ
测试2
测试3
测试4
PQR
测试5
预期产出:

<?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>

基础知识
测试1
XYZ
测试2
PQR
测试5
问题是如果我使用模板匹配,例如

如中所述,然后它会完全删除所有内容,因为main/item/value也是空的


我需要的是在元素为空时删除,但仅当元素没有子元素时才删除。

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


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

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
因此,模板匹配它,但不输出它

试试这个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>

如果我没有看错,您需要执行以下操作:

XSLT1.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>


这将删除没有包含某些内容的
值的
项。

此外,如果键test1和test2的值为空,则顶级项元素也应从输出中排除。我尝试过它不起作用,并给出xslt编译错误。错误:XSLTProcessor::transformToXml():XmlXPathCompiledVal:1堆栈上剩余的对象。@Ady211您确定您使用的是XSLT 2.0,正如您问题上的标记所示吗?我使用的是XSLT 1.0。这很有效。这个xslt如何区分main/item/value(它是空的并且有子节点item)和item/value?是不是(*)在耍把戏?是的。执行
not(*)
检查是否缺少子元素,因此它将只匹配“叶”元素。
<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>