Chris E
Chris E

Reputation: 3

XSLT: Remove empty elements from a certain depth

I am trying to create an xslt that will 'cleanse' the output of many different processes. I want to remove all empty elements, but some should always be present.

So for example the following

<soap:Envelope>
  <soap:Body>
    <typ:GetSomeStuffReturn>
      <typ:abcd>qwer</typ:abcd>
      <typ:efgh/>
      <typ:ijkl>asdf</typ:ijkl>
    </typ:GetSomeStuffReturn>
  </soap:Body>
</soap:Envelope> 

Should become

<soap:Envelope>
  <soap:Body>
    <typ:GetSomeStuffReturn>
      <typ:abcd>qwer</typ:abcd>
      <typ:ijkl>asdf</typ:ijkl>
    </typ:GetSomeStuffReturn>
  </soap:Body>
</soap:Envelope>     

Easy enough, plenty of examples how to achieve this.

However, this example

<soap:Envelope>
  <soap:Body>
    <typ:GetSomeStuffReturn>
      <typ:abcd/>
      <typ:efgh/>
      <typ:ijkl/>
    </typ:GetSomeStuffReturn>
  </soap:Body>
</soap:Envelope> 

Should become

<soap:Envelope>
  <soap:Body>
    <typ:GetSomeStuffReturn/>
  </soap:Body>
</soap:Envelope>  

I cannot work out how to do this. Everything I have tried works with one or the other example, but never both.

It is further complicated in that the code also needs to work irrespective of what the third node is, it will most likely always end in 'Return'

I always need the Envelope, the Body, and the third node so

<soap:Envelope>
  <soap:Body>
    <typ2:LookupThingsReturn>
      <typ2:wxyz/>
      <typ2:stuv/>
    </typ2:LookupThingsReturn>
  </soap:Body>
</soap:Envelope>

Should become

<soap:Envelope>
  <soap:Body>
    <typ2:LookupThingsReturn/>
  </soap:Body>
</soap:Envelope>  

Any help or advice gratefully received.

Upvotes: 0

Views: 108

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 117043

Try:

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="*[not(node()) and count(ancestor::*) > 2]"/>

</xsl:stylesheet>

Upvotes: 1

Related Questions