Removing Nodes for XML using XSLT - Don't need CRLF against removed nodes/fields

StackOverflow https://stackoverflow.com/questions/23653556

  •  22-07-2023
  •  | 
  •  

Question

I am using following XSLT to remove empty nodes from the XML. It is working fine by removing the empty nodes but it is also adding CRLF in place of removed nodes.

<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
  <xsl:template match="*[not(child::node())]"/>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

Extra CRLFs

I don't need these CRLFs. Please suggest!

Was it helpful?

Solution

It's not adding anything, but it is also not removing the left over whitespace text nodes between the elements in the original XML. If your XML has no mixed content then the simplest approach is to remove all the whitespace-only text nodes and then re-indent the result tree:

<xsl:strip-space elements="*" />
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" indent="yes" />

If you need to preserve the indentation from the original XML then you need to be slightly more creative

<xsl:template match="*[not(child::node())]"/>
<xsl:template match="text()[not(normalize-space())]
               [preceding-sibling::node()[1][self::*][not(child::node())]]" />

The second template will squash whitespace-only text nodes that immediately follow an element that has been squashed by the first template.

OTHER TIPS

It might simply be that e.g.

<root>
  <foo></foo>
  <foo>2</foo>
</root>

results in

<root>

  <foo>2</foo>
</root>

as your code removes the element but not any preceding or trailing white space text node.

In many cases simply doing

<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" indent="yes"/>
<xsl:strip-space elements="*"/>

avoids the problem and gives you nice and consistent indentation.

Or you need to write templates ensuring that a white space text node before or after an empty element is removed as well.

Other solution which worked for me was by using translate. Below is the XSLT:

<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
  <xsl:template match="*[not(child::node())]"/>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="text()">
    <xsl:value-of select="translate(., '&#10;&#13;', '')"/>
  </xsl:template>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top