By Pztar


2012-07-31 16:09:46 8 Comments

I'm having trouble understanding the difference between text() and node(). From what I understand, text() would be whatever is in between the tags <item>apple</item> which is apple in this case. Node would be whatever that node actually is, which would be item

But then I've been assigned some work where it asks me to "Select the text of all items under produce" and a separate question asks "Select all the manager nodes in all departments"

How is the output suppose to look text() as opposed to node()

Snippet of XML:

<produce>
 <item>apple</item>
 <item>banana</item>
 <item>pepper</item>
</produce>

<department>
 <phone>123-456-7891</phone>
 <manager>John</manager>
</department>

Of course, there are more departments and more managers, but this was just a snippet of code.

Any help would be much appreciated!

2 comments

@Tomalak 2012-07-31 16:27:16

text() and node() are node tests, in XPath terminology (compare).

Node tests operate on a set (on an axis, to be exact) of nodes and return the ones that are of a certain type. When no axis is mentioned, the child axis is assumed by default.

There are all kinds of node tests:

  • node() matches any node (the least specific node test of them all)
  • text() matches text nodes only
  • comment() matches comment nodes
  • * matches any element node
  • foo matches any element node named "foo"
  • processing-instruction() matches PI nodes (they look like <?name value?>).
  • Side note: The * also matches attribute nodes, but only along the attribute axis. @* is a shorthand for attribute::*. Attributes are not part of the child axis, that's why a normal * does not select them.

This XML document:

<produce>
    <item>apple</item>
    <item>banana</item>
    <item>pepper</item>
</produce>

represents the following DOM (simplified):

root node
   element node (name="produce")
      text node (value="\n    ")
      element node (name="item")
         text node (value="apple")
      text node (value="\n    ")
      element node (name="item")
         text node (value="banana")
      text node (value="\n    ")
      element node (name="item")
         text node (value="pepper")
      text node (value="\n")

So with XPath:

  • / selects the root node
  • /produce selects a child element of the root node if it has the name "produce" (This is called the document element; it represents the document itself. Document element and root node are often confused, but they are not the same thing.)
  • /produce/node() selects any type of child node beneath /produce/ (i.e. all 7 children)
  • /produce/text() selects the 4 (!) whitespace-only text nodes
  • /produce/item[1] selects the first child element named "item"
  • /produce/item[1]/text() selects all child text nodes (there's only one - "apple" - in this case)

And so on.

So, your questions

  • "Select the text of all items under produce" /produce/item/text() (3 nodes selected)
  • "Select all the manager nodes in all departments" //department/manager (1 node selected)

Notes

  • The default axis in XPath is the child axis. You can change the axis by prefixing a different axis name. For example: //item/ancestor::produce
  • Element nodes have text values. When you evaluate an element node, its textual contents will be returned. In case of this example, /produce/item[1]/text() and string(/produce/item[1]) will be the same.
  • Also see this answer where I outline the individual parts of an XPath expression graphically.

@Michael Kay 2012-08-01 08:32:44

It's an excellent answer, but for the record, there are a couple of inaccuracies. (a) The meaning of the node-test "*" depends on the axis: with most axes, it selects element nodes, but with the attribute axis it selects attributes, and with the namespace axis it selects namespaces. (b) @* and @foo are not node-tests, but axis steps, consisting of two parts: an axis (@, which is short for attribute::), and a node-test (* or foo).

@Tomalak 2012-08-01 08:43:45

@MichaelKay Thank you for the clarification. I'll modify the misleading bits. Axes are outside the scope of this question anyway, but it's hard to avoid mentioning them once you're talking about XPath.

@Danil Speransky 2012-07-31 16:21:30

Select the text of all items under produce:

//produce/item/text()

Select all the manager nodes in all departments:

//department/*

Related Questions

Sponsored Content

4 Answered Questions

7 Answered Questions

[SOLVED] Extract value of attribute node via XPath

  • 2011-01-29 08:31:10
  • Rehman
  • 395359 View
  • 249 Score
  • 7 Answer
  • Tags:   xml xpath

2 Answered Questions

[SOLVED] Text editor to open big (giant, huge, large) text files

1 Answered Questions

[SOLVED] xpath index text node

  • 2018-11-20 21:31:19
  • Shawn Li
  • 30 View
  • 1 Score
  • 1 Answer
  • Tags:   xml xpath

7 Answered Questions

[SOLVED] Getting attribute using XPath

  • 2010-12-25 22:47:41
  • GurdeepS
  • 340106 View
  • 324 Score
  • 7 Answer
  • Tags:   xml xpath

6 Answered Questions

[SOLVED] xpath find if node exists

13 Answered Questions

[SOLVED] What's the difference between an element and a node in XML?

  • 2008-09-25 10:47:53
  • Philip Morton
  • 210885 View
  • 353 Score
  • 13 Answer
  • Tags:   xml xmlnode

3 Answered Questions

[SOLVED] Select text from a node and omit child nodes

  • 2011-03-03 14:47:22
  • Dave
  • 3250 View
  • 6 Score
  • 3 Answer
  • Tags:   xpath xquery

1 Answered Questions

[SOLVED] Use xpath to select a node which has a greatest value for an attribute

  • 2016-02-12 20:03:27
  • Patrick Grayson
  • 740 View
  • 2 Score
  • 1 Answer
  • Tags:   xml xpath

1 Answered Questions

Validating xml node values using XPath

  • 2014-06-02 11:19:56
  • Web Nash
  • 157 View
  • 0 Score
  • 1 Answer
  • Tags:   xpath

Sponsored Content