Introduction

Based on a section of easy-to-read XML source data, I'll show you how to select and locate XML nodes and navigate through them using XPathNavigator and XPathNodeIterator. I will provide a few straightforward samples about XPath expression with which you could follow without difficulty. In the last part, there is some sample code to update, insert and remove XML nodes.

Some Concepts

XML - Extensible Markup Language, describe data structures in text format and with your own vocabularies, which means it does not use predefined tags and the meaning of these tags are not well understood.

XSL - Extensible Stylesheet Language, is designed for expressing stylesheets for XML documents. XSL is to XML as CSS is to HTML.

XML Transformation - is a user-defined algorithm that transforms a given XML document to another format, such as XML, HTML, XHTML. The algorithm is described by XSL.

XSLT - is designed for use as part of XSL, transforming an XML document into another XML document, or another type of document that is recognized by a browser, like HTML or XHTML. XSLT uses XPath.

XPath - is a set of syntax rules for defining parts of an XML document.

To keep this article simple and clear, I'll break it down into two parts, and put XSL, XSLT to my next article.

In the above code, we used "/catalog/cd/price" to select all the price elements. If you just want to select all the cd elements with price greater than 10.0, you can use "/catalog/cd[price>10.0]". Here are some more examples of XPath expressions:

/catalog

selects the root element

/catalog/cd

selects all the cd elements of the catalog element

/catalog/cd/price

selects all the price elements of all the cd elements of the catalog element

/catalog/cd[price>10.0]

selects all the cd elements with price greater than 10.0

starts with a slash(/)

represents an absolute path to an element

starts with two slashes(//)

selects all elements that satisfy the criteria

//cd

selects all cd elements in the document

/catalog/cd/title | /catalog/cd/artist

selects all the title and artist elements of the cd elements of catalog

//title | //artist

selects all the title and artist elements in the document

/catalog/cd/*

selects all the child elements of all cd elements of the catalog element

/catalog/*/price

selects all the price elements that are grandchildren of catalog

/*/*/price

selects all price elements which have two ancestors

//*

selects all elements in the document

/catalog/cd[1]

selects the first cd child of catalog

/catalog/cd[last()]

selects the last cd child of catalog

/catalog/cd[price]

selects all the cd elements that have price

/catalog/cd[price=10.90]

selects cd elements with the price of 10.90

/catalog/cd[price=10.90]/price

selects all price elements with the price of 10.90

//@country

selects all "country" attributes

//cd[@country]

selects cd elements which have a "country" attribute

//cd[@*]

selects cd elements which have any attribute

//cd[@country='UK']

selects cd elements with "country" attribute equal to 'UK'

To update a cd node, first I search out which node you are updating by SelectSingleNode, and then create a new cd element. After setting the InnerXml of the new node, call ReplaceChild method of XmlElement to update the document. The code is as follows:

Similarly, use InsertAfter and RemoveChild to insert and remove a node, check it out in the demo. When you run the application, make sure that "data.xml" is in the same directory as the EXE file.

Points of Interest

Anyway, XmlDocument is an in-memory or cached tree representation of an XML document. It is somewhat resource-intensive, if you have a large XML document and not enough memory to consume, use XmlReader and XmlWriter for better performance.

History

Version 1.0, it's my first article on CP, I expect there are many flaws. The XML source data and the knowledge comes from the web and MSDN, I just wrote a demo app to show them. No copyright reserved.

I wanna use the same code for a word document, but as the tags have a qualifier (like ), it doesn't work.
If I put it gives this error: "Namespace Manager or XsltContext needed. This query has a prefix, variable, or user-defined function."
And if I just put , there is no error but it doesn't go through the tags.

Hello i would like to parse the below XML file:
Can i get code snippet in where in i like to get the values 'P1', 'P2' when i query for the nodes "Display\PROCESSES\PROCESSTOP" and subsequently i like to get the values 'f1.doc' and 'f1.txt' when i query "Display\FILES\WINDOWS"/
<?xmlversion="1.0"encoding="utf-8"?><ROOT><Display><PROCESSES><PROCESSSTOP>P1</PROCESSSTOP><PROCESSSTOP>P2</PROCESSSTOP><PROCESSSTOP>P3</PROCESSSTOP><PROCESSSTOP>P4</PROCESSSTOP><PROCESSSTOP>P5</PROCESSSTOP><PROCESSSTOP>P6</PROCESSSTOP><PROCESSSTART>%ProgramFiles%\Windows Sidebar\sidebar.exe*/D "%ProgramFiles%\Windows Sidebar" /NORMAL "%ProgramFiles%\Windows Sidebar\sidebar.exe</PROCESSSTART></PROCESSES><SERVICES><SERVICESTOP>SS1</SERVICESTOP><SERVICEDELETE>SD2</SERVICEDELETE><SERVICEDELETE>SD3</SERVICEDELETE><SERVICEDELETE>SD4</SERVICEDELETE><SERVICESTART>ss2</SERVICESTART></SERVICES><FILES><WINDOWS><FILE>f1.doc</FILE><FILE>f2.txt</FILE></WINDOWS><SYSTEM32><FILE>f1.dll</FILE><FILE>f2.dll</FILE></SYSTEM32><SYSWOW64><FILE>f1.log</FILE><FILE>f2.log</FILE></SYSWOW64></FILES><DIRECTORIES><DIRECTORY>%HOMEDRIVE%\DIR1\</DIRECTORY><DIRECTORY>%LOCALAPPDATA%\DIR2\</DIRECTORY></DIRECTORIES><REGISTRY><HKEY_CLASSES_ROOT><KEY><RKEY></RKEY><KVAL>KeyVal1</KVAL><KVAL>KeyVal2</KVAL></KEY></HKEY_CLASSES_ROOT><HKEY_CURRENT_USER><KEY><RKEY>Software\</RKEY><KVAL>MyCompany</KVAL></KEY></HKEY_CURRENT_USER><HKEY_LOCAL_MACHINE><KEY><RKEY>Software\Classes\</RKEY><KVAL>LMKeyVal1</KVAL><KVAL>LMKeyVal2</KVAL></KEY><KEY><RKEY>Software\Classes\CLSID\</RKEY><KVAL>{4242B984-6C36-4FC8-8626-DE5E8B11886D}</KVAL><KVAL>{5E2121EE-0300-11D4-8D3B-444553540000}</KVAL></KEY><KEY><RKEY>Software\Classes\Wow6432Node\CLSID\</RKEY><KVAL>{0A9BD4EB-DED5-4DF0-BAF6-2CEA23F57261}</KVAL></KEY></HKEY_LOCAL_MACHINE></REGISTRY></Display></ROOT>

in a button click I would like to display the temperature of the day max and min. This is how I did it, but it's not working. Please help.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.XPath;

I found your post and example very informative and very useful. However, I am working on a project where I think we(the project) would be better served to use XML as a field in a data base table. The use (without telling what my company is doing) would be analogous to a proficiency test for students. For example say you are going to take a test of addition for all the the values of 1 (1 - 10) So the application will create the XML file or string with the root node being the <Test></Test> with a sibling node being <question>QuestionNum#</question> and a series of sibling nodes <problem>1 + 1</problem><solution>2</solution><answer>3</answer><durationtoanswer>10</durationtoanswer>

So the question is how can I extract the data from the database (row/column) into either a xml doc, or a dataset with a corresponding xsd (if necessary) so it can be used to test, update (answer) and write back to the database as a completed test?

hi,
I have few xpaths in one column of excel sheet like
Group/GroupID
Group/RatingDate
Group/CreatedDate
Group/GroupName
Group/CreatedBy
Group/SourceApplication .....
There are many more like this and there are many more subnodes to it
and my requirement is to create xml file using using these xpaths.
how to do this? is this possible to create xml file using these xpaths.
Plz suggest me.

"Pinky, are you thinking what im thinking?"
"I Dunno brain, how many licks DOES it take to get to the tootsie roll center of a tootsie pop?"
"You want me to calculate that? or should we take over the world?"
"ooh! OooooOOOooH! lets find out!"

Does anyone know of any class that allows the user to edit the attribute/values of the underlying xmlelement, but prevent him from adding/removing siblings/childnodes/new attributes? What I am trying to do is to use XML as a replacement for a struct, so the user can edit the values of existing fields, but cannot change the underlying xml structure.

I've been trying to populate a combo box with distinct items from an XML. Originaly i was retrieving the nodes and looping around the combo to see if the item already existed in the combo box. This , I thought was very inefficient.

searching for select distinct xpath wasnt turning up any sensible results. After a lot of hunting i managed to do it and thought this was a good place to share it.

Using the code in this article I added a textbox and a button to the form so I could play with different queries.

The button calls GetElements passing it the text in the text box (an xpath query). no rocket science here.
Edit the following line in GetElements method to return a clearer message in the listview
//listBox1.Items.Add("price: " + nav2.Value);
listBox1.Items.Add(nav2.Name + ": " + nav2.Value);

here are some examples of xpath queries that return distinct values from the xml provided in this editorial.

//cd[not(@country=preceding-sibling::cd/@country)]/@country

//cd[not(artist=preceding-sibling::cd/artist)]/artist

the first returns distinct countries using the attribute country in the cd element
the second returns distinct artists using the artist element.

Thanks for the article. It guided me along today as I edited my machine.config file. I had two big hurdles that I had to overcome, and wanted to share my experience. Namespaces such as xmlns="urn:schemas-microsoft-com:asm.v1" and when nodes being replaced are a bit deeper than the example.

Here is how i grabed the dependentAssembly node using name spaces
//build the namespace manager
//http://www.adlnet.org/forums/messageview.cfm?catid=15&threadid=1247&enterthread=y
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("bindings","urn:schemas-microsoft-com:asm.v1");

and later to do a replace of a node, I had to back track a bit to be at the proper insertion point
//Replace new binding with old binding
XmlNode nodeInsert = root.SelectSingleNode(sNodeXPath, nsmgr);
nodeInsert.ParentNode.ReplaceChild(newBinding, oldBinding);