23

I am writing an XSL transformation. I want to write a template which matches all the child elements of the document except one particular node. My xml looks like this -

<Document>
    <NodeA></NodeA>

    <NodeB></NodeB>

    <ServiceNode></ServiceNode>

    <NodeX></NodeX>
</Document>

I want to write a template that matches all nodes except ServiceNode i.e. NodeA to NodeX. How to write this Xpath to get -

<xsl:template match="ALL Nodex Except ServiceNode">
Serge Wautier
  • 21,494
  • 13
  • 69
  • 110
Unmesh Kondolikar
  • 9,256
  • 4
  • 38
  • 51

5 Answers5

36

I want to write a template that matches all nodes except ServiceNode i.e. NodeA to NodeX.

If by "node" you mean element, then use:

<xsl:template match="*[not(self::ServiceNode)]">

If by "node" you mean any node (of type element, text, comment, processing-instruction): use

<xsl:template match="node()[not(self::ServiceNode)]">

If you want only children of Document to be matched use:

<xsl:template match="Document/node()[not(self::ServiceNode)]">

If you want only children of the top element to be matched use:

<xsl:template match="/*/node()[not(self::ServiceNode)]">
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
7

You should better use this expression:

*[not(self::ServiceNode)]

As incorporated in an XSLT:

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

    <xsl:template match="/*">
        <xsl:apply-templates select="*[not(self::ServiceNode)]"/>
    </xsl:template>

    <xsl:template match="*">
        <xsl:value-of select="."/>
        <xsl:text>&#xA;</xsl:text>
    </xsl:template>

</xsl:stylesheet>

With this XML sample:

<Document>
    <NodeA>1</NodeA>
    <NodeB>2</NodeB>
    <ServiceNode>3</ServiceNode>
    <NodeX>4</NodeX>
</Document>

It will give a correct result:

1
2
4
Flack
  • 5,862
  • 2
  • 23
  • 27
5
<xsl:template match="Document/*[name() != 'ServiceNode']">

(or local-name() if you have to deal with namespaces)

slugster
  • 49,403
  • 14
  • 95
  • 145
user568826
  • 581
  • 5
  • 16
  • I recommend testing in a live evaluator like http://www.whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm where you can paste expressions like //*[name()!="pet"] – Chris Dolan Feb 01 '11 at 07:26
3

You could use two templates:

<xsl:template match="Document/*">
   ...do something...
</xsl:template>


<xsl:template match="Document/ServiceNode" />

The later template will take priority, so the first template will match everything except ServiceNode.

Nick Jones
  • 6,413
  • 2
  • 18
  • 18
  • This could be useful in some cases, besides it doesn't answer this question properly. –  Feb 01 '11 at 16:53
0
/Document/*[not(name()='ServiceNode')]
Amit Patel
  • 15,609
  • 18
  • 68
  • 106