Using XML in Your Application


Now that you know how to create XML documents, it is time to put this knowledge to use. the .NET Framework includes a number of namespaces and classes that makes it quite simple to read, manipulate, and write XML. The following pages cover at a number of these classes and examine how you can use them to create and manipulate XML programmatically.

XML Document Object Model

The XML Document Object Model (XML DOM) is a set of classes used to access and manipulate XML in a very intuitive way. The DOM is perhaps not the quickest way to read XML data, but as soon as you understand the relationship between the classes and the elements of an XML document, you are going to find it very easy to use.

The classes that make up the DOM can be found in the namespace System.Xml. The are a number of classes and namespaces in this namespace, but in this chapter you are going to focus on only a few of the classes that allow you to easily manipulate XML. The classes you are going to examine and use are described in the following table.

Class Name

Description

XmlNode

This class represents a single node in a document tree. It is the base of many of the classes you'll see in this chapter. If this node represents the root of an XML document, you will be able to navigate to any position in the document from it.

XmlDocument

The XmlDocument class extends the XmlNode class, but is often the first object you use when using XML. This is because this class is used to load and save data from disk or elsewhere.

XmlElement

The XmlElement class represents a single element in the XML document. the XmlElement is derived from XmlLinkedNode, which in turn is derived from XmlNode.

XmlAttribute

This class represents a single attribute. Like the XmlDocument class, it is derived from the XmlNode class.

XmlText

Represents the text between a beginning and closing tag.

XmlComment

Represents a special kind of node that is not regarded as part of the document other than to provide information to the reader about parts of the document.

XmlNodeList

The XmlNodeList class represents a collection of nodes.

XmlDocument Class

Usually, the first thing your application will want to do with XML is to read it from disk. As described in the preceding table, this is the domain of the XmlDocument class. You can think of the XmlDocument as an in-memory representation of the file on disk. Once you have used the XmlDocument class to load a file into memory, you can obtain the root node of the document from it and start reading and manipulating the XML:

 using System.Xml; . . . XmlDocument document = new XmlDocument(); document.Load(@"C:\Beginning Visual C#\Chapter 23\books.xml"); 

The two lines of code create a new instance of the XmlDocument class and load the file books.xml into it. Remember that the XmlDocument class is located in the System.Xml namespace, and you should insert a using System.Xml; in the using section at the beginning of the code.

In addition to loading and saving the XML, the XmlDocument class is also responsible for maintaining the XML structure itself. Because of this you will find a large number of methods on this class that are used to create, alter, and delete nodes in the tree. You will look at some of those methods shortly, but to present the methods properly, you need to know a bit more about another class, the XmlElement.

XmlElement Class

Now that the document has been loaded into memory, you want to do something with it. the DocumentElement property of the XmlDocument instance you created in the preceding code will return an instance of an XmlElement that represents the root element of the XmlDocument. This element is important because once you have that, you have access to every bit of information in the document:

XmlDocument document = new XmlDocument(); document.Load(@"C:\Beginning Visual C#\Chapter 23\books.xml"); XmlElement element = document.DocumentElement; 

After you've got the root element of the document, you are ready to use the information. the XmlElement class contains methods and properties for manipulating the nodes and attributes of the tree. Let's examine the methods for navigating the XML elements first.

Property Name

Description

FirstChild

This property returns the first child element after this one. If you recall the books.xml file from earlier in the chapter, the root node of the document was called "books" and the next node after that was "book." In that document, then, the first child of the root node "books" is "book."

<books> Root node
<book> FirstChild

nodeFirstChild returns an XmlNode object, and you should test for the type of the returned node as it is unlikely to always be an XmlElement instance. In the books example, the child of the Title element is, in fact, an XmlText node that represents the text Beginning Visual C#.

LastChild

This property operates exactly like the FirstChild property, except that it returns the last child of the current node. In the case, of the books example, the last child of the "books" node will still be a "book" node, but it will be the node representing the "Professional C# 2nd Edition" book.

<books> Root node
<book> FirstChild
<title>Beginning Visual C#</title>
<author>Karli Watson</author>
<code>7582</code>
</book>
<book> LastChild
<title>Professional C# 2nd Edition</title>
<author>Simon Robinson</author>
<code>7043</code>
</book>
</books>

ParentNode

This property returns the parent of the current node. In the books example, the "books" node is the parent of both of the "book" nodes.

NextSibling

Where the FirstChild and LastChild properties returned the leaf node of the current node, the NextSibling node returns the next node that has the same parent node. In the case of the books example, this means that getting the NextSibling of the title element will return the author element and calling NextSibling on that will return the code element.

HasChildNodes

This handy property allows you to check if the current element has child elements without actually getting the value from FirstChild and examining that against null.

Using the four properties from the preceding table, it is possible to run through an entire XmlDocument, as shown in the following Try It Out.

Try It Out – Looping through All Nodes in an XML Document

image from book

In this example, you are going to create a small Windows Forms application that loops through all the nodes of an XML document and prints out the name of the element or the text contained in the element in the case of an XmlText element.

  1. Begin by creating a new Windows Form project by selecting File New Project... In the dialog, select Windows Application. Name the project LoopThroughXmlDocument and press Enter.

  2. Design the form as shown in Figure 23-5 by dragging a ListBox and a Button control onto the form.

    image from book
    Figure 23-5

  3. Name the ListBox listBoxXmlNodes and the button buttonLoopThroughDocument.

  4. Double-click the button and enter the code that follows. Don't forget to add using System.Xml; to the using section at the top of the file:

    private void buttonLoopThroughDocument_Click(object sender, EventArgs e) { // Clear ListBox listBoxXmlNodes.Items.Clear(); // Load the XML document XmlDocument document = new XmlDocument(); document.Load(@"C:\Beginning Visual C#\Chapter 23\Books.xml"); // Use recursion to loop through the document. RecurseXmlDocument((XmlNode)document.DocumentElement, 0);     }     private void RecurseXmlDocument(XmlNode root, int indent) { // Make sure we don't do anything if if (root == null) return; if (root is XmlElement) // Root is an XmlElement type { // first, print the name listBoxXmlNodes.Items.Add(root.Name.PadLeft(root.Name.Length + indent)); // Then check if there are any child nodes and if there are, call this // method again to print them. if (root.HasChildNodes) RecurseXmlDocument(root.FirstChild, indent + 2); // Finally check to see if there are any siblings and if there are // call this method again to have them printed. if (root.NextSibling != null) RecurseXmlDocument(root.NextSibling, indent); } else if (root is XmlText) { // Print the text. string text = ((XmlText)root).Value; listBoxXmlNodes.Items.Add(text.PadLeft(text.Length + indent)); } } 

  5. Run the application and click Loop. You should get a result like that shown in Figure 23-6.

    image from book
    Figure 23-6

You'll notice the output doesn't look like it is valid XML, and obviously it isn't. The thing to notice is that when you ran through the elements of the XML document, you didn't encounter a single closing tag. In other words, you never have to worry whether the current element is a starting tag or a closing tag — the XmlNode or XmlElement instance represents the entire node, not just the text representation of a tag.

How It Works

When you click the button the first thing that happens is the XmlDocument method Load is called. This method loads the XML from a file into the XmlDocument instance, which can then be used to access the elements of the XML. Then you call a method that will allow you to loop through the XML recursively, passing the root node of the XML document to the method. The root element is obtained with the property DocumentElement of the XmlDocument class. Aside from the check for null on the root parameter that is passed into the RecurseXmlDocument method the first line of notice is the if sentence:

if (root is XmlElement) // Root is an XmlElement type {    ... } else if (root is XmlText) {    ... }

Recall that the is operator lets you examine the type of an object and returns true if the instance is of the specified type. Even though the root node is declared as an Xmlnode, that is merely the base type of the objects you are going to work with. But using the is operator to test the type of the objects you are able to determine the type of the objects runtime and behave accordingly.

Inside the two if blocks you add the appropriate text to the list view. Notice that the reason you have to know the type of the current instance of root is that the information you want to display is obtained differently for different elements: You want to display the name of XmlElements and the value of XmlText elements. The reason you only call RecurseXmlDocument recursively if the node is an XmlElement is that XmlText nodes never have child nodes.

image from book

Changing the Values of Nodes

Before you examine how to change the value of a node, it is important to realize that very rarely is the value of a node a simple thing. In fact, you will find that although all of the classes that derive from XmlNode include a property called Value, it very rarely returns anything useful to you. While this can feel like a bit of a letdown at first, you'll find it is actually quite logical that it must be so. Examine the books example from earlier:

<books>   <book>     <title>Beginning Visual C#</title>     <author>Karli Watson</author>     <code>7582</code>   </book>   <book> </books> 

Every single one of the tag pairs in the document resolves into a node in the DOM. Remember that when you looped through all the nodes in the document, you encountered a number of XmlElement nodes and three XmlText nodes. the XmlElement nodes in the XML above are <books>, <book>, <title>, <author>, and <code>. The XmlText nodes are the text between the starting and closing tags of title, author, and code. Though it could be argued that the value of title, author, and code is the text between the tags, that text is itself a node and it is that node that actually holds the value. The other tags clearly have no value associated with them other than other nodes.

If you look toward the bottom of the code in the RecurseXmlDocument method above, you will find the following line in the if block that executes when the current node is an XmlText node:

string text = ((XmlText)root).Value;

Here, you see that the Value property of the XmlText node instance is used to get the value of the node.

Nodes of the type XmlElement will return null if you use their Value property, but it is possible to get the information between the starting and closing tags of an XmlElement if you use one of two other methods: InnerText and InnerXml. This means that you are able to manipulate the value of nodes using two methods and a property, as described in the following table.

Property Name

Description

InnerText

This property gets the text of all the child nodes of the current node and returns it as a single concatenated string. This means that if you get the value of InnerText from the book node in the XML above, you will see the string "Beginning Visual C#Karli Watson7582" returned. If you get the InnerText of the title node, only "Beginnning Visual C#" is returned.

You can set the text using this method, but be careful if you do so, because it is quite possible to overwrite information you did not want to change if you set the text of a wrong node.

InnerXml

The InnerXml property returns the text like InnerText, but it also returns all of the tags. This means that if you get the value of InnerXml on the book node the result is the following string:

<title>Beginning Visual C#</title><author>Karli Watson
</author><code>7582</code>

As you can see, this can be quite useful if you have a string containing XML that you want to inject directly into your XML document. However, you are entirely responsible for the string yourself, and if you insert badly formed XML the application will generate an exception.

Value

The Value property is the "cleanest" way to manipulate information in the document, but as mentioned earlier, only a few of the classes actually return anything useful to you when you get the value. The classes that will return the desired text are:

XmlText
XmlComment
XmlAttribute

Inserting New Nodes

Now that you've seen that you can move around in the XML document and even get the values of the elements, let's examine how to change the structure of the document by adding nodes to the books document you've been using until now.

To insert new elements in the list, you are going to need to examine the new methods that are placed on the XmlDocument and XmlNode classes, shown in the following table. the XmlDocument class has methods that allow you to create new XmlNode and XmlElement instances, which is nice because both of these classes have only a protected constructor, which means you cannot create an instance of either directly with new.

Method Name

Description

CreateNode

The CreateNode method can be used to create any kind of node. There are three overloads of the method, two of which allow you to create nodes of the type found in the XmlNodeType enumeration and one that allows you to specify the type of node to use as a string. Unless you are quite sure about specifying a node type other than those in the enumeration, I strongly recommend using the two overloads that use the enumeration.

The method returns an instance of XmlNode that can then be cast to the appropriate type explicitly.

CreateElement

This method is simply a version of CreateNode that can only create nodes of the XmlDocument variety.

CreateAttribute

Again, this is simply a version of CreateNode that can only create nodes of the XmlAttribute variety.

CreateTextNode

CreateTextNode method creates, yes, you guessed it, nodes of the type XmlTextNode.

CreateComment

I've included this method in this list to show how diverse are the types of nodes that can be created. This method doesn't create a node that is actually part of the data represented by the XML document, but rather it is a comment meant for any human eyes that might have to read the data. You can pick up comments when reading the document in your applications as well.

The methods in the preceding table are all used to create the nodes themselves, but after calling any of them you really have to do something with them before they become interesting. Immediately after creation the nodes have no additional information about them, and they are not yet inserted into the document. To do either you should use methods that are found on any class derived from XmlNode (including XmlDocument and XmlElement). They following table describes those methods.

Method Name

Description

AppendChild

This simple-to-use method appends a child node to a node of type XmlNode or derived type. It is important to remember that the node you append appears at the bottom of the list of children of the node on which the method is called. If you don't care about the order of the children there's no problem, but if you do you should remember to append the nodes in the correct sequence.

InsertAfter

By using the InsertAfter method, you can control exactly where you want to insert the new node. The method takes two parameters, one of which is the new node and the second of which is the node after which the new node should be inserted.

InsertBefore

This method works exactly like InsertAfter, except that the new node is inserted before the node you supply as a reference.

In the Following Try It Out, you build on the previous example and insert a book node in the books.xml document. There is no code in the example to clean the document (yet), so if you run it several times you will probably end up with a lot of identical nodes.

Try It Out – Creating Nodes

image from book

Follow these steps to add a node to the books.xml document.

  1. Add a button beneath the existing button on the form and name it buttonCreateNode. Change its Text property to Create Node.

  2. Double-click the new button, and enter the following code:

        private void buttonCreateNode_Click(object sender, EventArgs e)     { // Load the XML document. XmlDocument document = new XmlDocument(); document.Load(@"C:\Beginning Visual C#\Chapter 23\Books.xml"); // Get the root element. XmlElement root = document.DocumentElement; // Create the new nodes. XmlElement newBook = document.CreateElement("book"); XmlElement newTitle = document.CreateElement("title"); XmlElement newAuthor = document.CreateElement("author"); XmlElement newCode = document.CreateElement("code"); XmlText title = document.CreateTextNode("Beginning Visual C# 3rd Edition"); XmlText author = document.CreateTextNode("Karli Watson et al"); XmlText code = document.CreateTextNode("1234567890"); XmlComment comment = document.CreateComment("This book is the book you are reading"); // Insert the elements. newBook.AppendChild(comment); newBook.AppendChild(newTitle); newBook.AppendChild(newAuthor); newBook.AppendChild(newCode); newTitle.AppendChild(title); newAuthor.AppendChild(author); newCode.AppendChild(code); root.InsertAfter(newBook, root.FirstChild); document.Save(@"C:\Beginning Visual C#\Chapter 23\Books.xml");     } 

  3. Add the following code to the end of the RecurseXmlDocument method:

     else if (root is XmlComment) { // Print text. string text = root.Value; listBoxXmlNodes.Items.Add(text.PadLeft(text.Length + indent)); // Then check if there are any child nodes, and if there are call this // method again to print them. if (root.HasChildNodes) RecurseXmlDocument(root.FirstChild, indent + 2); // Finally, check to see if there are any siblings, and if there are // call this method again to have them printed. if (root.NextSibling != null) RecurseXmlDocument(root.NextSibling, indent); } 

  4. Run the application and click Create Node. Then click Loop, and you should see the dialog shown in Figure 23-7.

    image from book
    Figure 23-7

There is one important type of node that you didn't create in the preceding example: the XmlAttribute. I will leave this for an exercise at the end of the chapter.

How It Works

The code in the buttonCreateNode_Click method is where all the creation of nodes happens. It creates eight new nodes, four of which are of type XmlElement, three of type XmlText, and finally one of type XmlComment.

All of the nodes are created with the method of the encapsulating XmlDocument instance. the XmlElement nodes are created with the CreateElement method, the XmlText nodes are created with the CreateTextNode method, and the XmlComment node is created with the CreateComment method.

After the nodes have been created, they still need to be inserted into the XML tree. This is done with the AppendChild method on the element to which the new node should become a child. The only exception to this is the book node that is the root node of all of the new nodes. This node is inserted into the tree using the InsertAfter method of the root object. Whereas all of the nodes that are inserted using AppendChild always become the last of the list of child nodes, InsertAfter allows you to position the node where you want it.

image from book

Deleting Nodes

Now that you've seen how to create new nodes, all that is left is to learn how to delete them again. All classes derived from XmlNode include a number of methods, shown in the following table, that allow you to remove nodes from the document.

Method Name

Description

RemoveAll

Rather unsurprisingly, this method will remove all child nodes in the node on which it is called. What is slightly less obvious is that it will also remove all attributes on the node, because they are regarded as child nodes as well.

RemoveChild

This method will remove a single child in the node on which it is called. The method returns the node that has been removed from the document, but you can reinsert it if you change your mind.

The following short Try It Out extends the Windows Forms application you've been creating over the past two examples to include the capability to delete nodes. For now, all that it does is find the last instance of the book node and remove it.

Try It Out – Removing Nodes

image from book

The following steps let you find and remove the final instance of the book node.

  1. Add a new button below the two that already exist and name it buttonDeleteNode. Set its Text property to Delete Node.

  2. Double-click the new button and enter the following code:

     private void buttonDeleteNode_Click(object sender, EventArgs e) { // Load the XML document. XmlDocument document = new XmlDocument(); document.Load(@"C:\Beginning Visual C#\Chapter 23\Books.xml"); // Get the root element. XmlElement root = document.DocumentElement; // Find the node. root is the <books> tag, so its last child  // which will be the last <book> node. if (root.HasChildNodes) { XmlNode book = root.LastChild; // Delete the child. root.RemoveChild(book); // Save the document back to disk. document.Save(@"C:\Beginning Visual C#\Chapter 23\Books.xml"); } } 

  3. Run the application. Note that when you click the Delete Node button and then the Loop button, the last node in the tree will disappear.

How It Works

After the initial steps to load the XML into the XmlDocument object, you examine the root element to see if there are any child elements in the XML you loaded. If there are, you use the LastChild property of the XmlElement class to get the last child. After that, removing the element is as simple as calling RemoveChild, passing in the instance of the element that you wish to remove, in this case the last child of the root element.

image from book

Selecting Nodes

You now know how to move back and forth in an XML document, how to manipulate the values of the document, how to create new nodes, and how to delete them again. Only one thing remains in this chapter: how to select nodes without having to traverse the entire tree.

The XmlNode class includes two methods commonly used to select nodes from the document without running through every node in it. These are SelectSingleNode and SelectNodes (described in the following table), both of which use a special query language, called XPath, to select the nodes. You learn about that shortly.

Method Name

Description

SelectSingleNode

This method is used to select a single node. If you create a query that fetches more than one node, only the first node will be returned.

SelectNodes

This method returns a node collection in the form of an XmlNodesList class.

XPath

XPath is a query language for XML documents much as SQL is for relational databases. It is used by the two methods described in the previous table to let you avoid the hassle of walking the entire tree of an XML document. It does take a little getting used to, however, because the syntax is nothing like SQL or C#.

Note

XPath is quite extensive, and only a small part of it is covered here to allow you to start selecting nodes. If you are interested in learning more, you should take a look at www.w3.org/TR/xpath and the Visual Studio help pages.

To properly see the XPath in action, you are going to use a slightly extended version of the books.xml file. It is listed in its entirety in the "Selecting Nodes" Try It Out example later in the chapter, and it can be found on this book's Website as XPathQuery.xml.

The following table lists some of the most common operations you can perform with XPath. If nothing else is stated, then the XPath query example will make a selection that is relative to the node on which it is performed. Where it is necessary to have a name of a node, you can assume that the current node is the <book> node in the XML document above.

Purpose

XPath Query Example

Select the current node.

.

Select the parent of the current node.

..

Select all child nodes of the current node.

*

Select all child nodes with a specific name — in this case title.

title

Select an attribute of the current node.

@pages

Select all attributes of the current node.

@*

Select a child node by index — in this case the second author node.

author[2]

Select all the text nodes of the current node.

text()

Select one or more grandchildren of the current node.

author/text()

Select all nodes in the document with a particular name — in this case all title nodes.

//title

Select all nodes in the document with a particular name and particular parent name — in this case the parent name is book and node name is title.

//book/title

Select a node where a value criteria is met — in this case, the books where the author Jacob Hammer Pedersen participated.

//book[author='Jacob Hammer Pedersen']

Select a node where an attribute value criteria is met — in this case the pages attribute = 1000.

//book[@pages= '1000']

In the following Try It Out, you'll create a small application that will allow you to execute and see the results of a number of predefined queries, as well as allow you to enter your own queries.

Try It Out – Selecting Nodes

image from book

As previously mentioned, this example uses an extended version of the books.xml file seen earlier in this chapter. You can download the file from the book's Website or type it in from the listing here:

<?xml version="1.0"?> <books>   <book pages="944">     <title>Beginning Visual C#</title>     <author>Karli Watson</author>     <author>Jacob Hammer Pedersen</author>     <author>Christian Nagel</author>     <author>David Espinosa</author>     <author>Zach Greenvoss</author>     <author>Jon D. Reid</author>     <author>Matthew Reynolds</author>     <author>Morgan Skinner</author>     <author>Eric White</author>     <code>7582</code>   </book>   <book pages="1000">     <title>Beginning Visual C# 3rd Edition</title>     <author>Karli Watson</author>     <author>Jacob Hammer Pedersen</author>     <author>Christian Nagel</author>     <author>Jon D. Reid</author>     <author>Morgan Skinner</author>     <author>Eric White</author>     <code>1234567890</code>   </book>   <book pages="1272">     <title>Professional C# 2nd Edition</title>     <author>Simon Robinson</author>     <author>Scott Allen</author>     <author>Ollie Cornes</author>     <author>Jay Glynn</author>     <author>Zach Greenvoss</author>     <author>Burton Harvey</author>     <author>Christian Nagel</author>     <author>Morgan Skinner</author>     <author>Karli Watson</author>     <code>7043</code>   </book> </books>

Save the XML file as XPathQuery.xml. Remember to change the path to the file in the code that follows.

Follow these steps to create a Windows Forms application with querying capability.

  1. Create a new Windows Forms application and name it XmlQueryExample.

  2. Create the dialog shown in Figure 23-8. Name the TextBox textBoxQuery. All the other controls should be named with their type followed by their text property (that is, the name of the radio button "Set Book as current" is radioButtonSetBookAsCurrent and the Close button is buttonClose).

    image from book
    Figure 23-8

  3. Right-click the form and choose View Code. The first thing is to include the using directive:

     using System.Xml; 
  4. Next, add two private fields to hold the document and current node, and initialize them in the constructor:

     private XmlDocument mDocument; private XmlNode mCurrentNode;     public Form1() {   InitializeComponent();     mDocument = new XmlDocument(); mDocument.Load(@"C:\Beginning Visual C#\Chapter 23\XPathQuery.xml"); mCurrentNode = mDocument.DocumentElement; ClearListBox(); }

  5. Next, you need a few helper methods to display the result of the queries in the list box:

     private void DisplayList(XmlNodeList nodeList) { foreach (XmlNode node in nodeList) { RecurseXmlDocumentNoSiblings(node, 0); } } private void RecurseXmlDocumentNoSiblings(XmlNode root, int indent) { // Make sure we don't do  if (root == null) return; if (root is XmlElement) // Root is an XmlElement type { // First, print the name. listBoxResult.Items.Add(root.Name.PadLeft(root.Name.Length + indent)); // Then check if there are any child nodes and if there are, call this // method again to print them. if (root.HasChildNodes) RecurseXmlDocument(root.FirstChild, indent + 2); } else if (root is XmlText) { // Print the text. string text = ((XmlText)root).Value; listBoxResult.Items.Add(text.PadLeft(text.Length + indent)); } else if (root is XmlComment) { // Print text. string text = root.Value; listBoxResult.Items.Add(text.PadLeft(text.Length + indent)); // Then check if there are any child nodes and if there are, call this // method again to print them. if (root.HasChildNodes) RecurseXmlDocument(root.FirstChild, indent + 2); } } private void RecurseXmlDocument(XmlNode root, int indent) { // Make sure we don't do anything if  if (root == null) return; if (root is XmlElement) // Root is an XmlElement type. { // First, print the name. listBoxResult.Items.Add(root.Name.PadLeft(root.Name.Length + indent)); // Then check if there are any child nodes and if there are, call this // method again to print them. if (root.HasChildNodes) RecurseXmlDocument(root.FirstChild, indent + 2); // Finally check to see if there are any siblings, and if there are // call this method again to have them printed. if (root.NextSibling != null) RecurseXmlDocument(root.NextSibling, indent); } else if (root is XmlText) { // Print the text. string text = ((XmlText)root).Value; listBoxResult.Items.Add(text.PadLeft(text.Length + indent)); } else if (root is XmlComment) { // Print text. string text = root.Value; listBoxResult.Items.Add(text.PadLeft(text.Length + indent)); // Then check if there are any child nodes. and if there are call this // method again to print them. if (root.HasChildNodes) RecurseXmlDocument(root.FirstChild, indent + 2); // Finally, check to see if there are any siblings, and if there are // call this method again to have them printed. if (root.NextSibling != null) RecurseXmlDocument(root.NextSibling, indent); } } private void ClearListBox() { listBoxResult.Items.Clear(); } private void buttonClose_Click(object sender, EventArgs e) { Application.Exit(); } 

  6. Next, insert the code to perform the queries on the XML into the SelectionChange event of the radio buttons:

     private void radioButtonSelectRoot_CheckedChanged(object sender, EventArgs e) { mCurrentNode = mDocument.DocumentElement.SelectSingleNode("//books"); ClearListBox(); RecurseXmlDocument(mCurrentNode, 0); } private void radioButtonSelectAllAuthors_CheckedChanged(object sender, EventArgs e) { if (mCurrentNode != null) { XmlNodeList nodeList = mCurrentNode.SelectNodes("//book/author"); ClearListBox(); DisplayList(nodeList); } else ClearListBox(); } private void radioButtonSelectBySpecificAuthor_CheckedChanged(object sender, EventArgs e) { if (mCurrentNode != null) { XmlNodeList nodeList = mCurrentNode. Hammer Pedersen']"); ClearListBox(); DisplayList(nodeList); } else ClearListBox(); } private void radioButtonSelectAllBooks_CheckedChanged(object sender, EventArgs e) { if (mCurrentNode != null) { XmlNodeList nodeList = mCurrentNode.SelectNodes("//book"); ClearListBox(); DisplayList(nodeList); } else ClearListBox(); } private void radioButtonSetBookAsCurrent_CheckedChanged(object sender, EventArgs e) { if (mCurrentNode != null) { mCurrentNode = mCurrentNode. C#']"); ClearListBox(); RecurseXmlDocumentNoSiblings(mCurrentNode, 0); } else ClearListBox(); } private void radioButtonSetBooksAsCurrent_CheckedChanged(object sender, EventArgs e) { if (mCurrentNode != null) { mCurrentNode = mCurrentNode.SelectSingleNode("//books"); ClearListBox(); RecurseXmlDocumentNoSiblings(mCurrentNode, 0); } else ClearListBox(); } private void radioButtonSelectAllChildren_CheckedChanged(object sender, EventArgs e) { if (mCurrentNode != null) { XmlNodeList nodeList = mCurrentNode.SelectNodes("*"); ClearListBox(); DisplayList(nodeList); } else ClearListBox(); } 

  7. Finally, insert the code that executes whatever the user has entered in the TextBox and the code that closes the application when the buttonClose button is clicked:

     private void buttonExecute_Click(object sender, EventArgs e) { if (textBoxQuery.Text == "") return; try { XmlNodeList nodeList = mCurrentNode.SelectNodes(textBoxQuery.Text); ClearListBox(); DisplayList(nodeList); } catch (System.Exception err) { MessageBox.Show(err.Message); } } private void buttonClose_Click(object sender, EventArgs e) { Application.Exit(); } 

  8. Run the application. Note how the values change as you click the radio buttons.

How It Works

The first two methods, RecurseXmlDocumentNoSiblings and RecurseXmlDocument, and DisplayList are used to make the listings in the list box. The reason you need more than one of these methods is that you want to be able to more tightly control the output.

The code that does the actual searching in the XML is all found in the code in steps 6 and 7. The method SelectNodes of the XmlNode class is used to execute searches that can or should return multiple nodes. This method returns an XmlNodeList object, which is then passed to the DisplayList helper method.

The other method that is used to search through the XML is SelectSingleNode. This method, as the name suggests, returns a single node, which you pass to the RecurseXmlNodeNoSiblings helper method to display the current node and its child nodes.

The following table lists the XPath queries that are used in the methods and what they do.

XPath

Description

//book/author

This selects all the nodes in the XML that have the name author and the parent book.

//book[author='Jacob Hammer Pedersen']

Selects all the book nodes in the XML that have a child node with the name author that has the value Jacob Hammer Pedersen.

//book

Selects all the book nodes in the XML.

book[title='Beginning Visual C#']

Selects the book node with the title node that equals Beginning Visual C#.

//books

Selects all books nodes.

*

Selects all child nodes of the current node.




Beginning Visual C# 2005
Beginning Visual C#supAND#174;/sup 2005
ISBN: B000N7ETVG
EAN: N/A
Year: 2005
Pages: 278

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net