RaiBnod
RaiBnod

Reputation: 2351

Removing useless tag in XML from XSLT

I have following output in XML and i have problem on removing useless tags from the content. I have following XML values:

<Site EntityType="2" Identifier="CL">
  <Name Last="Rai"/>
  <Address/>
    <Contacts>
      <Contact>
        <Number/>
          </Contact>
      </Contacts>
</Site>

My question is how to remove useless tag from above XML using XSLT?

Desire output is like this:

<Site EntityType="2" Identifier="CL">
  <Name Last="Rai"/>    
</Site>

In above input <Address/>, <Contacts>...</Contacts> makes no sense so we are deleting those contents.

Upvotes: 0

Views: 316

Answers (1)

Tim C
Tim C

Reputation: 70648

In situations like this you should start off with the identity template which will copy across all existing nodes and attributes

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

This means you only need to write templates for the nodes you wish to remove. Taking you definition of "useless" as "elements with no descendant text nodes (or processing instructions), and with no attributes and no descendant elements with attributes", then the template match would you like this

 <xsl:template match="*[not(descendant-or-self::*/@*|descendant::text()[normalize-space()]|descendant::processing-instruction())]" />

Try this XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" />
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="*[not(descendant-or-self::*/@*|descendant::text()[normalize-space()]|descendant::processing-instruction())]" />
</xsl:stylesheet>

Alternatively, if you use xsl:strip-space, you could adjust it slightly to this:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" />
  <xsl:strip-space elements="*" />
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="*[not(descendant-or-self::*/@*|descendant::text()|descendant::processing-instruction())]" />
</xsl:stylesheet>

Upvotes: 2

Related Questions