通过 XSLT 删除 XML 空元素

问题描述

SAP 正在发送 XML 有效负载 (IDOC) 中的空元素。我们需要从有效负载删除下面 IDOC 中的空元素 (<E1EDK02 SEGMENT="1"></E1EDK02>)。我使用了一个 XSLT 脚本来删除这些空元素,但我仍然看到下面的 XSLT,空元素没有被删除,但它们被转换为 <E1EDK02 SEGMENT="1"/>。任何人都可以帮助我们删除 Empty 的 XSLT 代码

来自 SAP 的 IDOC

<?xml version="1.0" encoding="UTF-8"?><ORDERS05>
<IDOC BEGIN="1">
    <EDI_DC40 SEGMENT="1">
        <TABNAM>XXX</TABNAM>
        <MANDT>XXX</MANDT>
        <IDOCTYP>XXX</IDOCTYP>
    </EDI_DC40>
    <E1EDK02 SEGMENT="1">
        <QUALF>001</QUALF>
        <BELNR>TEST</BELNR>
        <DATUM>20210317</DATUM>
    </E1EDK02>
    <E1EDK02 SEGMENT="1"></E1EDK02>
    <E1EDK02 SEGMENT="1">
        <QUALF>002</QUALF>
        <BELNR>TEST</BELNR>
        <DATUM>20210317</DATUM>
    </E1EDK02>
    <E1EDK02 SEGMENT="1"></E1EDK02>
</IDOC></ORDERS05>

使用 XSLT

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes" />
<xsl:template match="@*|node()">
    <xsl:if test=". != '' or ./@* != ''">
        <xsl:copy>
            <xsl:apply-templates  select="@*|node()"/>
        </xsl:copy>
    </xsl:if>
</xsl:template></xsl:stylesheet>

预期产出

<?xml version="1.0" encoding="UTF-8"?><ORDERS05>
<IDOC BEGIN="1">
    <EDI_DC40 SEGMENT="1">
        <TABNAM>XXX</TABNAM>
        <MANDT>XXX</MANDT>
        <IDOCTYP>XXX</IDOCTYP>
    </EDI_DC40>
    <E1EDK02 SEGMENT="1">
        <QUALF>001</QUALF>
        <BELNR>TEST</BELNR>
        <DATUM>20210317</DATUM>
    </E1EDK02>
    <E1EDK02 SEGMENT="1">
        <QUALF>002</QUALF>
        <BELNR>TEST</BELNR>
        <DATUM>20210317</DATUM>
    </E1EDK02>
</IDOC></ORDERS05>

解决方法

您的测试:

<xsl:if test=". != '' or ./@* != ''">

传递任何具有非空属性的元素。您要删除的元素:

<E1EDK02 SEGMENT="1"></E1EDK02>

有一个 SEGMENT 属性,并且该属性有一个值 - 因此,它通过了您的测试。


如果你想删除没有子元素或文本节点的元素,我建议你这样做:

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

<!-- remove empty elements -->
<xsl:template match="*[not(node())]"/>

</xsl:stylesheet>