RE: [xsl] Empty nodes AND attributes stripping - I'm so lost - SOLUTION

Subject: RE: [xsl] Empty nodes AND attributes stripping - I'm so lost - SOLUTION
From: "Passin, Tom" <tpassin@xxxxxxxxxxxx>
Date: Thu, 2 Sep 2004 14:47:25 -0400
> From: Kevinjohn Gallagher [mailto:web_design_guru@xxxxxxxxxxx]
>
> Firstly, thanks for all the help.
>
> I'm including my solution here so others might benefit.
>
> <?xml version="1.0" encoding="UTF-16"?>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
> version="1.0">
> <xsl:output method="xml" />
> <xsl:strip-space elements="*"/>
>
> 	<xsl:template match="//parent/myContent//@*|node()">
> 		<xsl:copy>
> 			<xsl:apply-templates select="@*|node()"/>
> 		</xsl:copy>
> 	</xsl:template>
>
> 	<xsl:template match="@*[.='']"/>
> 	<xsl:template match="//parent/myContent/*[.='' and
> not(attribute::*)]"/>
>
> </xsl:stylesheet>

Some suggestions... No need to write //parent, because parent is already
the document element.  /parent will do fine, an avoid possibly multiple
scanning of the whole tree.

In the third template match, you can just write
   match="*[.='' and not(@*)]"

Actually, your stylesheet does copy empty elements (if they have no
attributes), for example, if you add an empty element as an immediate
child of a myContent element, and I don't think that is what you want

However, you can simplify this further (and eliminate the empty child
element problem mentioned above) by doing all your filtering in the
select specification, like this -

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

<xsl:template match="/parent/myContent//@*|node()">
   <xsl:copy>
      <xsl:apply-templates
     select="myContent | @*[.!='']|node()[@*[. != ''] or not(.='')]"/>
   </xsl:copy>
</xsl:template>

</xsl:stylesheet>

This selects for copying only those attributes that have text, or those
nodes that either have non-empty attributes or non-empty content, or all
myContent elements even if they are empty.  I believe that this is what
you want, and if not, it should be easy to adjust the filter.

The principle here is to select just the nodes you want, where that is
possible.  The selection works as simply as this here because of the
//@* |node() in the initial select.  Thus, all nodes of whatever depth
selected in the inner apply-templates get handled by the same template.
This way, there is no need for your second and third templates at all,
the one template handles everything.

 Sometimes you have to make sure that the default templates do not kick
in, but in this example there is no such problem.

BTW, the value of doing as much filtering as possible in your select
specifications is something I learned from this list, and it has stood
me in good stead.

Cheers,

Tom P

Current Thread