Re: [xsl] Filter out elements that have one specific sub-element and nothing else

Subject: Re: [xsl] Filter out elements that have one specific sub-element and nothing else
From: "Andrew Welch" <andrew.j.welch@xxxxxxxxx>
Date: Wed, 21 Feb 2007 13:19:30 +0000
On 2/21/07, stephan@xxxxxxxxxx <stephan@xxxxxxxxxx> wrote:
Hi there,

I have an XML file like this:

<?xml version="1.0" encoding="UTF-8"?>
<funnylist>
    <listitem>
        <formatinfo color="yellow" />
        <stuffinside>Info</stuffinside> MoreInfo
    </listitem>
    <listitem>
        <formatinfo color="blue" />
    </listitem>
    <listitem>
        <formatinfo color="red" />EvenMoreInfo
    </listitem>
</funnylist>

I need to filter out this element:
    <listitem>
        <formatinfo color="blue" />
    </listitem>

The rule: if listitem contains only formatinfo and no other element or
text then remove it.

I have no clue how to formulate the xPath.
Help appreciated.

This is XSLT's party piece - you need an "identity" template, and then a specific "no-op" template matching the element you want to suppress:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

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

<!-- no-op template -->
<xsl:template match="listitem[formatinfo][count(child::*) = 1]"/>

</xsl:stylesheet>

The "identity template" traverses the source tree copying each node to
the result tree.  The "no-op" template overrides the generic identity
template for nodes that it matches, and it doesn't copy the nodes -
hence "no-op".

In this case, the no-op template will only suppress <listitem>'s with
a single <formatinfo> - if you need it to do more then post back.

cheers
andrew

Current Thread