tags:

views:

33

answers:

2

The overall goal is to remove all empty nodes--including nodes which would be made empty if the child empty nodes were removed. The following:

<xsl:template match="*[not(node())]"/>

will remove empty nodes, but will leave empty nodes that had only empty nodes in them previously. I think I need an xpath that will match all nodes that all descendants of which have no attributes and no text nodes (ignoring whitespace).

A: 

I think I found the answer...

<xsl:template match="*[not(.//text() | .//@*)]"/>

Just find all nodes that have no descendant text or attributes, right? Is there something I'm missing such that this won't do what I think it will in some cases? In my simple test, this seemed to work.

taotree
This *is* correct, but may cause some XSLT processors that don't have good optimizers to perform the union before concluding this is a match. See my solution, which might have a better chance of being optimized, as it uses explicit `and`.
Dimitre Novatchev
+3  A: 

Use:

<xsl:template match="*[not(.//@*) and not(descendent::text())]"/>

Notice the and operator. Using or does not solve the problem.

Dimitre Novatchev
@Dimitre: In logic this would be equivalent `*[not(.//@* or descendent::text())]`, but I do not know if it is difficult to optimize.
Alejandro