Selecting All but a Specific Element
Problem
You want to select all elements in a specific context, except the ones you choose to exclude.
Solution
The best way to select all but a specific element is to say:
<xsl:apply-templates select="*[not(self::element-to-ignore)]"/>
or, if iterating, say:
<xsl:for-each select="*[not(self::element-to-ignore)]"> ... </xsl:for-each>
Discussion
When XSLT newbies first need to select all but a specific element, they will probably think of the following construct first:
<xsl:apply-templates select="*[name( ) != 'element-to-ignore']"/>
This code works in many cases, but it could cause trouble when the
document uses namespaces. Recall that name( )
returns the node’s
QName: the namespace prefix concatenated to the local part of the
name. However, in any given XML document, nothing forces the author
to use a specific prefix:
<!--This will fail if the author decided to use SALES:product instead of sales:product --> <xsl:apply-templates select="*[name( ) != 'sales:product']"/>
Alternatively, you could use local-name( ).
However, this prefix would ignore elements from all namespaces that
have that particular local name, which might not be what you want.
This recommendation applies only in the case of elements, not
attributes. If you need to select all but a specific attribute, use
local-name( ). The self axis, when applied to a
name, refers only to elements. In other words, use
<xsl:copy-of select=@*[local-name( ) != 'ignored-attribute']/> and not <xsl:copy-of ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access