[Page 963 (
continued
)]
19.8. (Optional) Document Object Model (DOM)
Although an XML document is a text file, retrieving data from the document using traditional sequential file processing techniques is
neither
practical nor efficient,
especially
for adding and removing elements dynamically.
Upon successfully parsing a document, some XML parsers store document data as tree structures in memory. Figure 19.21 illustrates the tree structure for the root element of the document
article.xml
discussed in Fig. 19.2. This hierarchical tree structure is called a
Document Object Model
(
DOM
)
tree
, and an XML parser that creates this type of structure is known as a
DOM parser
. Each element
name
(e.g.,
article
,
date
,
firstName
) is represented by a node. A node that contains other nodes (called
child nodes
or children) is called a
parent node
(e.g.,
author
). A parent node can have many children, but a child node can have only one parent node. Nodes that are peers (e.g.,
firstName
and
lastName
) are called
sibling nodes
. A node's
descendant nodes
include its children, its children's children and so on. A node's
ancestor
nodes
include its parent, its parent's parent and so on.
The DOM tree has a single
root node
, which contains all the other nodes in the document. For example, the root node of the DOM tree that represents
article.xml
(Fig. 19.2) contains a node for the XML declaration (line 1), two nodes for the comments (lines 23) and a node for the XML document's root element
article
(line 5).
Classes for creating, reading and manipulating XML documents are located in the C# namespace
System.Xml
. This namespace also contains additional namespaces that provide other XML-
related
operations.
[Page 964]
Reading an XML Document with an
XmlReader
In this section, we present several examples that use DOM trees. Our first example, the program in Fig. 19.22, loads the XML document presented in Fig. 19.2 and displays its data in a text box. This example uses class
XmlReader
to iterate through each node in the XML document.
Figure 19.22. XmlReader iterating through an XML document.
1
// Fig. 19.22: XmlReaderTest.cs
2
// Reading an XML document.
3
using
System;
4
using
System.Windows.Forms;
5
using
System.Xml;
6
7
namespace
XmlReaderTest
8
{
9
public partial class
XmlReaderTestForm : Form
10
{
[Page 965]
11
public
XmlReaderTestForm()
12
{
13
InitializeComponent();
14
}
// end constructor
15
16
// read XML document and display its content
17
private void
XmlReaderTestForm_Load(
object
sender, EventArgs e )
18
{
19
// create the XmlReader object
20
XmlReaderSettings settings =
new
XmlReaderSettings();
21
XmlReader reader = XmlReader.Create(
"article.xml"
, settings );
22
23
int
depth =
-1
;
// tree depth is -1, no indentation
24
25
while
( reader.Read() )
// display each node's content
26
{
27
switch
( reader.NodeType )
28
{
29
case
XmlNodeType.Element
:
// XML Element, display its name
30
depth++;
// increase tab depth
31
TabOutput( depth );
// insert tabs
32
OutputTextBox.Text +=
"<"
+ reader.Name +
">\r\n"
;
33
34
// if empty element, decrease depth
35
if
(
reader.IsEmptyElement
)
36
depth--;
37
break
;
38
case
XmlNodeType.Comment
:
// XML Comment, display it
39
TabOutput( depth );
// insert tabs
40
OutputTextBox.Text +=
"<!--"
+ reader.Value +
"-->\r\n"
;
41
break
;
42
case
XmlNodeType.Text
:
// XML Text, display it
43
TabOutput( depth );
// insert tabs
44
OutputTextBox.Text +=
"\t"
+ reader.Value +
"\r\n"
;
45
break
;
46
47
// XML XMLDeclaration, display it
48
case
XmlNodeType.XmlDeclaration
:
49
TabOutput( depth );
// insert tabs
50
OutputTextBox.Text +=
"<?"
+ reader.Name +
" "
+
51
reader.Value +
"?>\n"
;
52
break
;
53
case
XmlNodeType.EndElement
:
// XML EndElement, display it
54
TabOutput( depth );
// insert tabs
55
OutputTextBox.Text +=
"</"
+ reader.Name +
">\r\n"
;
56
depth--;
// decrement depth
57
break
;
58
}
// end switch
59
}
// end while
60
}
// end method XmlReaderTextForm_Load
61
[Page 966]
62
// insert tabs
63
private void
TabOutput(
int
number )
64
{
65
for
(
int
i =
; i < number; i++ )
66
OutputTextBox.Text +=
"\t"
;
67
}
// end method TabOutput
68
}
// end class XmlReaderTestForm
69
}
// end namespace XmlReaderTest
|
Line 5 is a
using
declaration for the
System.Xml
namespace, which contains the XML classes used in this example. Class
XmlReader
is an
abstract
class that defines the interface for reading XML documents. We cannot create an
XmlReader
object directly. Instead, we must invoke
XmlReader
's
static
method
Create
to obtain an
XmlReader
reference (line 21). Before doing so, however, we must prepare an
XmlReaderSettings
object that specifies how we would like the
XmlReader
to behave (line 20). In this example, we use the default settings of the properties of an
XmlReaderSettings
object. Later, you will learn how to set certain properties of the
XmlReaderSettings
class to instruct the
XmlReader
to perform validation, which it does not do by default. The
static
method
Create
receives as arguments the name of the XML document to read and an
XmlReaderSettings
object. In this example the XML document
article.xml
(Fig. 19.2) is opened when method
Create
is invoked in line 21. Once the
XmlReader
is created, the XML document's contents can be read programmatically.
[Page 966]
Method
Read
of
XmlReader
reads one node from the DOM tree. By calling this method in the
while
loop condition (line 27),
reader Read
s all the document nodes. The
switch
statement (lines 2758) processes each node. Either the
Name
property (lines 32, 50 and 55), which contains the node's name, or the
Value
property (lines 40 and 44), which contains the node's data, is formatted and
concatenated
to the
string
assigned to the
TextBox
's
Text
property. The
XmlReader
's
NodeType
property specifies whether the node is an element, comment, text, XML declaration or end element. Note that each
case
specifies a node type using
XmlNodeType
enumeration constants. For example,
XmlNodeType.Element
(line 31) indicates the start tag of an element.
The displayed output emphasizes the structure of the XML document. Variable
depth
(line 23) maintains the number of tab
characters
to indent each element. The depth is incremented each time the program encounters an
Element
and is decremented each time the program encounters an
EndElement
or empty element. We use a similar technique in the
next
example to
emphasize
the tree structure of the XML document being displayed.
Displaying a DOM Tree Graphically in a
treeView
Control
XmlReader
s do not provide features for displaying their content graphically. In this example, we display an XML document's contents using a
TreeView
control. We use class
TreeNode
to represent each node in the tree. Class
treeView
and class
treeNode
are part of the
System.Windows.Forms
namespace.
treeNode
s are added to the
TReeView
to emphasize the structure of the XML document.
[Page 967]
The C# program in Fig. 19.23
demonstrates
how to manipulate a DOM tree programmatically to display it graphically in a
treeView
control. The GUI for this application contains a
TReeView
control named
xmlTreeView
(declared in
XmlDom.Designer.cs
). The application loads
letter.xml
(Fig. 19.24) into
XmlReader
(line 27), then displays the document's tree structure in the
TReeView
control. [
Note:
The version of
letter.xml
in Fig. 19.24 is nearly identical to the one in Fig. 19.4, except that Fig. 19.24 does not reference a DTD as line 5 of Fig. 19.4 does.]
Figure 19.23. DOM structure of an XML document displayed in a
treeView
.
1
// Fig. 19.23: XmlDom.cs
2
// Demonstrates DOM tree manipulation.
3
using
System;
4
using
System.Windows.Forms;
5
using
System.Xml;
6
7
namespace
XmlDom
8
{
9
public partial class
XmlDomForm : Form
10
{
11
public
XmlDomForm()
12
{
13
InitializeComponent();
14
}
// end constructor
15
16
private
TreeNode tree;
// TreeNode reference
17
18
// initialize instance
variables
19
private void
XmlDomForm_Load(
object
sender, EventArgs e )
20
{
21
// create Xml ReaderSettings and
22
// set the IgnoreWhitespace property
23
XmlReaderSettings settings =
new
XmlReaderSettings();
24
settings.IgnoreWhitespace =
true
;
25
26
// create XmlReader object
27
XmlReader reader = XmlReader.Create(
"letter.xml"
, settings );
28
29
tree =
new
TreeNode();
// instantiate TreeNode
30
31
tree.Text =
"letter.xml"
;
// assign name to TreeNode
32
xmlTreeView.Nodes.Add( tree );
// add TreeNode to TreeView
33
BuildTree( reader, tree );
// build node and tree hierarchy
34
}
// end method XmlDomForm_Load
35
36
// construct TreeView based on DOM tree
37
private void
BuildTree( XmlReader reader, TreeNode treeNode )
38
{
[Page 968]
39
// treeNode to add to existing tree
40
TreeNode newNode =
new
TreeNode();
41
42
while
( reader.Read() )
43
{
44
// build tree based on node type
45
switch
( reader.NodeType )
46
{
47
// if Text node, add its value to tree
48
case
XmlNodeType.Text
:
49
newNode.Text = reader.Value;
50
treeNode.Nodes.Add( newNode );
51
break
;
52
case
XmlNodeType.EndElement
:
// if EndElement, move up tree
53
treeNode = treeNode.Parent;
54
break
;
55
56
// if new element, add name and traverse tree
57
case
XmlNodeType.Element
:
58
59
// determine if element contains content
60
if
( !reader.IsEmptyElement )
61
{
62
// assign node text, add newNode as child
63
newNode.Text = reader.Name;
64
treeNode.Nodes.Add( newNode );
65
66
// set treeNode to last child
67
treeNode = newNode;
68
}
// end if
69
else
// do not traverse empty elements
70
{
71
// assign NodeType string to newNode
72
// and add it to tree
73
newNode.Text = reader.NodeType.ToString();
74
treeNode.Nodes.Add( newNode );
75
}
// end else
76
break
;
77
default
:
// all other types, display node type
78
newNode.Text = reader.NodeType.ToString();
79
treeNode.Nodes.Add( newNode );
80
break
;
81
}
// end switch
82
83
newNode =
new
TreeNode();
84
}
// end while
85
86
// update TreeView control
87
xmlTreeView.ExpandAll();
// expand tree nodes in TreeView
88
xmlTreeView.Refresh();
// force TreeView to update
89
}
// end method BuildTree
90
}
// end class XmlDomForm
91
}
// end namespace XmlDom
[Page 969]
|
Figure 19.24. Business letter
marked
up as XML.
(This item is displayed on page 970 in the print version)
1
<?xml version
=
"1.0"
?>
2
<!-- Fig. 19.24: letter.xml -->
3
<!-- Business letter formatted with XML -->
4
5
<letter>
6
<contact type
=
"sender"
>
7
<name>
Jane Doe
</name>
8
<address1>
Box 12345
</address1>
9
<address2>
15 Any Ave.
</address2>
10
<city>
Othertown
</city>
11
<state>
Otherstate
</state>
12
<zip>
67890
</zip>
13
<phone>
555-4321
</phone>
14
<flag gender
=
"F"
/>
15
</contact>
16
17
<contact type
=
"receiver"
>
18
<name>
John Doe
</name>
19
<address1>
123 Main St.
</address1>
20
<address2></address2>
21
<city>
Anytown
</city>
22
<state>
Anystate
</state>
23
<zip>
12345
</zip>
24
<phone>
555-1234
</phone>
25
<flag gender
=
"M"
/>
26
</contact>
27
28
<salutation>
Dear Sir:
</salutation>
29
30
<paragraph>
It is our privilege to
inform
you about our new database
31
managed with XML. This new system allows you to reduce the
32
load on your inventory list server by having the client machine
33
perform the work of sorting and filtering the data.
34
</paragraph>
35
36
<paragraph>
Please visit our Web site for availability
37
and pricing.
38
</paragraph>
39
40
<closing>
Sincerely,
</closing>
41
<signature>
Ms. Doe
</signature>
42
</letter>
|
In
XmlDomForm
's
Load
event handler (lines 1934), lines 2324 create an
XmlReaderSettings
object and set its
IgnoreWhitespace
property to
true
so that the insignificant whitespaces in the XML document are ignored. Line 27 then invokes
static XmlReader
method
Create
to parse and load
letter.xml
.
[Page 969]
Line 29 creates the
treeNode tree
(declared in line 16). This
TReeNode
is used as a graphical representation of a DOM tree node in the
TReeView
control. Line 31
assigns
the XML document's name (i.e.,
letter.xml
) to
tree
's
Text
property. Line 32 calls method
Add
to add the new
treeNode
to the
treeView
's
Nodes
collection. Line 33 calls method
BuildTree
to update the
treeView
so that it displays
source
's complete DOM tree.
Method
BuildTree
(lines 3789) receives an
XmlReader
for reading the XML document and a
treeNode
referencing the current location in the tree (i.e., the
treeNode
most recently added to the
treeView
control). Line 40 declares
treeNode
reference
newNode
, which will be used for adding new nodes to the
treeView
. Lines 4284 iterate through each node in the XML document's DOM tree.
The
switch
statement in lines 4581 adds a node to the
treeView
, based on the
XmlReader
's current node. When a text node is
encountered
, the
Text
property of the new
treeNode
newNode
is assigned the current node's value (line 49). Line 50 adds this
TReeNode
to
treeNode
's node list (i.e., adds the node to the
treeView
control).
Line 52 matches an
EndElement
node type. This
case
moves up the tree to the current node's parent because the end of an element has been encountered. Line 53
accesses
TReeNode
's
Parent
property to retrieve the node's current parent.
Line 57 matches
Element
node types. Each non-empty
Element NodeType
(line 60)
increases
the depth of the tree; thus, we assign the current
reader Name
to the
newNode
's
Text
property and add the
newNode
to
TReeNode
's node list (lines 6364). Line 67 assigns the
newNode
's reference to
TReeNode
to ensure that
treeNode
refers to the last child
TReeNode
in the node list. If the current
Element
node is an empty element (line 69), we assign to the
newNode
's
Text
property the string representation of the
NodeType
(line 73). Next, the
newNode
is added to the
TReeNode
node list (line 74). The default
case
(lines 7780) assigns the string representation of the node type to the
newNode Text
property, then adds the
newNode
to the
treeNode
node list.
After the entire DOM tree is
processed
, the
TReeNode
node list is displayed in the
treeView
control (lines 8788).
TReeView
method
ExpandAll
causes all the nodes of the tree to be displayed.
TReeView
method
Refresh
updates the display to show the newly added
TReeNode
s. Note that while the application is running, clicking nodes (i.e., the
+
or boxes) in the
treeView
either expands or collapses them.
[Page 970]
Locating Data in XML Documents with XPath
Although
XmlReader
includes
methods
for reading and modifying node values, it is not the most efficient means of locating data in a DOM tree. The Framework Class Library provides class
XPathNavigator
in the
System.Xml.XPath
namespace for iterating through node lists that match search criteria, which are written as XPath expressions. Recall that XPath (XML
Path
Language) provides a syntax for locating specific nodes in XML documents effectively and
efficiently
. XPath is a string-based language of expressions used by XML and many of its related technologies (such as XSLT, discussed in Section 19.7).
[Page 971]
Figure 19.25 uses an
XPathNavigator
to navigate an XML document and uses a
treeView
control and
treeNode
objects to display the XML document's structure. In this example, the
TReeNode
node list is updated each time the
XPathNavigator
is positioned to a new node, rather than displaying the entire DOM tree at once. Nodes are added to and deleted from the
treeView
to reflect the
XPathNavigator
's location in the DOM tree. Figure 19.26 shows the XML document
sports.xml
that we use in this example. [
Note:
The versions of
sports.xml
presented in Fig. 19.26 and Fig. 19.16 are nearly identical. In the current example, we do not want to apply an XSLT, so we omit the processing instruction found in line 2 of Fig. 19.16.]
Figure 19.25.
XPathNavigator
navigating selected nodes.
1
// Fig. 19.25: PathNavigator.cs
2
// Demonstrates class XPathNavigator.
3
using
System;
4
using
System.Windows.Forms;
5
using
System.Xml.XPath;
// contains XPathNavigator
6
7
namespace
PathNavigator
8
{
9
public partial class
PathNavigatorForm : Form
10
{
11
public
PathNavigatorForm()
12
{
13
InitializeComponent();
14
}
// end constructor
15
16
private
XPathNavigator xPath;
// navigator to traverse document
17
18
// references document for use by XPathNavigator
19
private
XPathDocument document;
20
21
// references TreeNode list used by TreeView control
22
private
TreeNode tree;
23
24
// initialize variables and TreeView control
25
private void
PathNavigatorForm_Load(
object
sender, EventArgs e )
26
{
27
// load XML document
28
document =
new
XPathDocument(
"sports.xml"
);
29
xPath = document.CreateNavigator();
// create navigator
30
tree =
new
TreeNode();
// create root node for TreeNodes
31
32
tree.Text = xPath.NodeType.ToString();
// #root
33
pathTreeView.Nodes.Add( tree );
// add tree
34
35
// update TreeView control
36
pathTreeView.ExpandAll();
// expand tree node in TreeView
37
pathTreeView.Refresh();
// force TreeView update
[Page 972]
38
pathTreeView.SelectedNode = tree;
// highlight root
39
}
// end method PathNavigatorForm_Load
40
41
// process selectButton_Click event
42
private void
selectButton_Click(
object
sender, EventArgs e )
43
{
44
XPathNodeIterator iterator;
// enables node iteration
45
46
try
// get specified node from ComboBox
47
{
48
// select specified node
49
iterator = xPath.Select( selectComboBox.Text );
50
DisplayIterator( iterator );
// print selection
51
}
// end try
52
// catch invalid expressions
53
catch
( System.Xml.XPath.XPathException argumentException )
54
{
55
MessageBox.Show( argumentException.Message,
"Error"
,
56
MessageBoxButtons.OK
,
MessageBoxIcon.Error
);
57
}
// end catch
58
}
// end method selectButton_Click
59
60
// traverse to first child on firstChildButton_Click event
61
private void
firstChildButton_Click(
object
sender, EventArgs e )
62
{
63
TreeNode newTreeNode;
64
65
// move to first child
66
if
(
xPath.MoveToFirstChild()
)
67
{
68
newTreeNode =
new
TreeNode();
// create new node
69
70
// set node's Text property to
71
// either navigator's name or value
72
DetermineType( newTreeNode, xPath );
73
74
// add nodes to TreeNode node list
75
tree.Nodes.Add( newTreeNode );
76
tree = newTreeNode;
// assign tree newTreeNode
77
78
// update TreeView control
79
pathTreeView.ExpandAll();
// expand node in TreeView
80
pathTreeView.Refresh();
// force TreeView to update
81
pathTreeView.SelectedNode = tree;
// highlight root
82
}
// end if
83
else
// node has no children
84
MessageBox.Show(
"Current Node has no children."
,
85
""
,
MessageBoxButtons.OK
,
MessageBoxIcon.Information
);
86
}
// end method firstChildButton_Click
87
88
// traverse to node's parent on parentButton_Click event
89
private void
parentButton_Click(
object
sender, EventArgs e )
90
{
[Page 973]
91
// move to parent
92
if
(
xPath.MoveToParent()
)
93
{
94
tree = tree.Parent;
95
96
// get number of child nodes, not including sub trees
97
int
count = tree.GetNodeCount(
false
);
98
99
// remove all children
100
for
(
int
i =
; i < count; i++ )
101
tree.Nodes.Remove( tree.FirstNode );
// remove child node
102
103
// update TreeView control
104
pathTreeView.ExpandAll();
// expand node in TreeView
105
pathTreeView.Refresh();
// force TreeView to update
106
pathTreeView.SelectedNode = tree;
// highlight root
107
}
// end if
108
else
// if node has no parent (root node)
109
MessageBox.Show(
"Current node has no parent."
,
""
,
110
MessageBoxButtons.OK
,
MessageBoxIcon.Information
);
111
}
// end method parentButton_Click
112
113
// find next sibling on nextButton_Click event
114
private void
nextButton_Click(
object
sender, EventArgs e )
115
{
116
// declare and initialize two TreeNodes
117
TreeNode newTreeNode =
null
;
118
TreeNode newNode =
null
;
119
120
// move to next sibling
121
if
(
xPath.MoveToNext()
)
122
{
123
newTreeNode = tree.Parent;
// get parent node
124
125
newNode =
new
TreeNode();
// create new node
126
127
// decide whether to display current node
128
DetermineType( newNode, xPath );
129
newTreeNode.Nodes.Add( newNode );
// add to parent node
130
131
tree = newNode;
// set current position for display
132
133
// update TreeView control
134
pathTreeView.ExpandAll();
// expand node in Tree''''View
135
pathTreeView.Refresh();
// force TreeView to update
136
pathTreeView.SelectedNode = tree;
// highlight root
137
}
// end if
138
else
// node has no additional siblings
139
MessageBox.Show(
"Current node is last sibling."
,
""
,
140
MessageBoxButtons.OK
,
MessageBoxIcon.Information
);
141
}
// end method nextButton_Click
[Page 974]
142
143
// get previous sibling on previousButton_Click
144
private void
previousButton_Click(
object
sender, EventArgs e )
145
{
146
TreeNode parentTreeNode =
null
;
147
148
// move to previous sibling
149
if
(
xPath.MoveToPrevious()
)
150
{
151
parentTreeNode = tree.Parent;
// get parent node
152
parentTreeNode.Nodes.Remove( tree );
// delete current node
153
tree = parentTreeNode.LastNode;
// move to previous node
154
155
// update TreeView control
156
pathTreeView.ExpandAll();
// expand tree node in TreeView
157
pathTreeView.Refresh();
// force TreeView to update
158
pathTreeView.SelectedNode = tree;
// highlight root
159
}
// end if
160
else
// if current node has no previous siblings
161
MessageBox.Show(
"Current node is first sibling."
,
""
,
162
MessageBoxButtons.OK
,
MessageBoxIcon.Information
);
163
}
// end method previousButton_Click
164
165
// print values for XPathNodeIterator
166
private void
DisplayIterator( XPathNodeIterator iterator )
167
{
168
selectTextBox.Clear();
169
170
// prints selected node's values
171
while
( iterator.MoveNext() )
172
selectTextBox.Text +=
iterator.Current.Value.Trim()
+
"\r\n"
;
173
}
// end method DisplayIterator
174
175
// determine if TreeNode should display current node name or value
176
private void
DetermineType( TreeNode node, XPathNavigator xPath )
177
{
178
switch
( xPath.NodeType )
// determine NodeType
179
{
180
case
XPathNodeType.Element:
// if Element, get its name
181
// get current node name, and remove whitespaces
182
node.Text = xPath.Name.Trim();
183
break
;
184
default
:
// obtain node values
185
// get current node value and remove whitespaces
186
node.Text = xPath.Value.Trim();
187
break
;
188
}
// end switch
189
}
// end method DetermineType
190
}
// end class PathNavigatorForm
191
}
// end namespace PathNavigator
[Page 975]
(a)
(b)
(c)
(d)
|
Figure 19.26. XML document that describes various sports.
(This item is displayed on page 976 in the print version)
1
<?xml version =
"1.0"
?>
2
<!-- Fig. 19.26: sports.xml -->
3
<!-- Sports Database -->
4
5
<sports>
6
<game id =
"783"
>
7
<name>
Cricket
</name>
8
9
<paragraph>
10
More popular among commonwealth nations.
11
</paragraph>
12
</game>
13
14
<game id =
"239"
>
15
<name>
Baseball
</name>
16
17
<paragraph>
18
More popular in America.
19
</paragraph>
20
</game>
21
22
<game id =
"418"
>
23
<name>
Soccer (Futbol)
</name>
24
25
<paragraph>
26
Most popular sport in the world.
27
</paragraph>
28
</game>
29
</sports>
|
[Page 975]
The program of Fig. 19.25 loads XML document
sports.xml
(Fig. 19.26) into an
XPathDocument
object by passing the document's file name to the
XPathDocument
constructor (line 28). Method
CreateNavigator
(line 29) creates and returns an
XPathNavigator
reference to the
XPathDocument
's tree structure.
The navigation methods of
XPathNavigator
are
MoveToFirstChild
(line 66),
MoveToParent
(line 92),
MoveToNext
(line 121) and
MoveToPrevious
(line 149). Each method
performs
the action that its name implies. Method
MoveToFirstChild
moves to the first child of the node referenced by the
XPathNavigator
,
MoveToParent
moves to the parent node of the node referenced by the
XPathNavigator
,
MoveToNext
moves to the next sibling of the node referenced by the
XPathNavigator
and
MoveToPrevious
moves to the previous sibling of the node referenced by the
XPathNavigator
. Each method returns a
bool
indicating whether the move was successful. In this example, we display a warning in a
MessageBox
whenever a move operation fails. Furthermore, each method is called in the event handler of the button that matches its name (e.g., clicking the
First Child
button in Fig. 19.25(a) triggers
firstChildButton_Click
, which calls
MoveToFirstChild
).
[Page 976]
Whenever we move forward using
XPathNavigator
, as with
MoveToFirstChild
and
MoveToNext
, nodes are added to the
treeNode
node list. The
private
method
DetermineType
(lines 176189) determines whether to assign the
Node
's
Name
property or
Value
property to the
TReeNode
(lines 182 and 186). Whenever
MoveToParent
is called, all the children of the parent node are removed from the display. Similarly, a call to
MoveToPrevious
removes
the current sibling node. Note that the nodes are removed only from the
TReeView
, not from the tree representation of the document.
The
selectButton_Click
event handler (lines 4258) corresponds to the
Select
button.
XPathNavigator
method
Select
(line 49) takes search criteria in the form of either an
XPathExpression
or a
string
that represents an XPath expression, and returns as an
XPathNodeIterator
object any node that matches the search criteria. Figure 19.27 summarizes the XPath expressions provided by this program's combo box. We show the result of some of these expressions in Figs. 19.25(b)(d).
[Page 977]
Figure 19.27.
XPath
expressions and descriptions.
|
XPath Expression
|
Description
|
|
/sports
|
Matches all
sports
nodes that are child nodes of the document root node.
|
|
/sports/game
|
Matches all
game
nodes that are child nodes of
sports
, which is a child of the document root.
|
|
/sports/game/name
|
Matches all
name
nodes that are child nodes of
game
. The
game
is a child of
sports
, which is a child of the document root.
|
|
/sports/game/paragraph
|
Matches all
paragraph
nodes that are child nodes of
game
. The
game
is a child of
sports
, which is a child of the document root.
|
|
/sports/game [name=
'Cricket'
]
|
Matches all
game
nodes that contain a child element whose name is
Cricket
. The
game
is a child of
sports
, which is a child of the document root.
|
Method
DisplayIterator
(defined in lines 166173) appends the node values from the given
XPathNodeIterator
to the
selectTextBox
. Note that we call
string
method
trim
to remove unnecessary whitespace. Method
MoveNext
(line 171) advances to the next node, which property
Current
(line 172) can access.
|