Using XPath Navigators C# Help

An XPathNavigator is used to select, iterate, and sometimes edit data from an XMLdocument,  An XPathNavigator can be created from an xmlDocument to allow editing capabilities or from an XPathDocument for read-only use. Because the XPathDocument is read-only, it performs very well, Unlike the xmlReader, the xpathNaviga~or isn’t a streaming model, so the same document can be used without having to re-read and parse.

The XPathNavigaor is part of the system.xml.xPathnamespace. XPath is a query language used to select specific nodes or elements from an XMLdocument for processing.

The System.Xml.XPath Namespace

The System. xml. XPath namespace is built for speed. It provides a read-only view of your XML documents, so there are no editing capabilities. Classes in this namespace are built to do fast iterationn and selections on the XMLdocument in a cursory fashion.

The following table lists the key classes in System. xml .XPath and gives a short description of the purpose of each class.

XPathDocument

XPathDocument doesn’t offer any of the functionality of the xmlDocument class. Its sole purpose is to create XPathNavigators. As a matter of fact, that is the only method available on the XPathDocument, class (other then those provided by Object).

An XPathDocument can be.created in a number of different ways. Youcan pass in an xmlReader, a file name of an XMLdocument or a Stream-based object to the constructor, This allows a great deal of flexibility. For example, you can use the xmlValidatingReader to validate the XMLand then use that same object to create the XPathDocument.

XPathNavigator

XPathNavigator contains all of the methods for moving and selecting elements that you need, The following table lists some of the “move” methods defined in this class.

In order to select a subset of the document you can use one of the Select methods listed in the following table.

If the XPathNavigator was created from an XPathJjur;wnent:, I is read-only, If it is created from anXm1Docwnent, the XPathNavigator can be used to edit the document, This call be verified by checking the CanEdi t property. If it is true, you can use one of the Insert methods. If sertBefore and InsertAfter will create a new node either before or after the current node. The source of the new node can be from an XmlReader or a string Optionally an xml writer can be returned and used to write the new node information, Strongly typed values can be read from the nodes using the Values As properties, Notice that this is different from reader, which used ReadValue methods.

XPathNodelterator

XPathNoc.eltarator can be thought of as the equivlent of a nodeList or a NodeSet in XPath, This object has three properties and two methods:

  1. Clone – Creates a new copy of itself
  2. Count – Number of nodes in the XPachNode terator object
  3. Current – Returns an XPath Navigator pointing to the current node
  4. CurrentPosit aon ( ) – Returns an integer with the current position
  5. MoveNext () – Moves to the next node that matches the XPath expression that created theXPathNodelterator

The XpathNodeIterator is returned by the XPathNav~gator Select methods. You use It to iterate over the set of nodes returned by a Select method of the XPathNavigator, Using the MoveNext method of the XPathNodeIterator does not change the location of the XPathNavigator that created it.

Using ‘Classes from the XPath Namespace

The best way to see how these classes are used is to look at some code that iterates through the books xml document. This 11 allow you to see how the navigation works. In order to use the examples, you first add a reference to the System.Xml.Xs1 and System.Xml.XPath namespaces:

using System.xml.XPath;
using Systern.Xml.Xsl;

For this example, you use the file booksxpa th. xml.lt is similar to the books. xml file that you have been using, except that there are a couple of extra books added, Here’s the form code, which is part of the Xml Sample project:

The first thing you do in the buttonl_Click () method is create the XPath Document (called doc), passing in the file and path string of the document you want opened. The next line is where the XPathNavigator is created:
XPathNavigator nav = doc.CreateNavigator();
In the example, you can see that you use the Select () method to retrieve a set of nodes that all have
novel as the value of the genre attribute. Youthen use the MoveNext () method to iterate through all the novels in the book list.

To load the data into the list box, you use the XPathNodeIterator. Current property. This creates a new XPathNavigator object based on just the node that the XPathNodeIterator is pointing to.

In this case, you are creating an XPathNavigator for one book node in the document, The next loop takes this XPathNavigator and creates another XPathNodeIterator by issuing another type of select method, the SelectDescendants () method. This gives you an XPathNodeIterator of all of the child nodes and children of the child nodes of the book node.

Then you do another MoveNext () loop on the XPathNodeIterator and load the text box with the element names and element values.

Figure 28-2 shows what the screen looks like after running the code. Note that novels are the only books listed now.

Figure 28-2

Figure 28-2

What if you wanted to add up the cost of these books? XPatllNavigator includes the Evaluate () method for just this reason. Evaluate () has three overloads. The first one contains a string that is the XPath function call. The second overload uses the XPathExpression object as a parameter, and the third uses XPathExpression and an XPathNodeIterator as parameters. The following code is similar to the previous example, except this time all of the nodes in the document are iterated. The Evaluate method call at the end totals up the QJStof all of the books:

private void button2_Click(object sender, EventArgs e)
(
llmodify to match your path structure
XPathDocument doc = new XPathDocument(‘books.xml’);
Ilcreate the XPath navigator
XPathNavigator nav = «IXPathNavigable)doc).treateNavigator();

Ilcreate the XPathNodelterator of book nodes
XPathNodelterator iter = nav.Select(“/bookstore/book”);
textBoxl.Text = “”; while (iter.MoveNext(»
(
XPathNodelterator newlter
iter.Current.SelectDescendants(XPathNodeType.Elernent, false);
while (newlter.MoveNext(»
(
textBoxl.Text += newlter.Current.Name + “: ” + newlter.Current.Value +
“\r\n” ;
)
)
textBoxl.Text += “=========================” + “\r\n”;
textBoxl.Text += “Total Cost = ” + nav.Evaluate(“sum(/bookstore/book/price)”);

This time, you see the totalcost of the books evaluated in the textbox (see Figure 28-3).

Figure 28-3

Figure 28-3

Now let’ssay that you need to add a node for discount. y~ can use the InsertAfter method to get this done fairly easily.Here is the code:

private void button3_Click(object sender, EventArgs e)
(
XmlDocument doc = new XmlDocument ();’
doc.Load(“books.xml”);
XPathNavigator nay doc.CreateNavigator();
if (nav.CanEdit)
(
XPathNodelterator iter = nav.Select(“/bookstore/book/price”);
while (iter.MoveNext{»
(
iter .Current .InsertAfter (“<disc>.5</disc>”) ;.
)
doc.Save(“newbooks.xml”);

Here, you add the <disc>5</disc> element after the price elements. First, all of the price nodes are selected. The XPathNodelterator is used \0 iterate over the nodes and the new node is inserted.

The modified document is saved with a new name, newbooks xml. The new version looks like the following:

Nodes’can be inserted before or after a selected node. The nodes can also be changed, and they can be deleted. If you have changes that have to  done to large numbers of nodes, using the XPathNavigator created from an XmlDocument may be your best choice.

The System.Xml.Xsl Namespace

The System.Xml. xsl namespace contains the classes that the .NET Framework uses to support XSL transforms. The contents of this namespace are available to any store whose classes implement the IXPathNavigable interface. In the .NET Framework, that would currently include XmlDocument, XmlDataDocument, and XPathDocument. Again, just as with XPath, use the store that makes the most sense. If you plan to create a custom store, such as one using the file system and you want to be able to do transforms, be sure to implement the IXPathNavigable interface in your class.

XSLT is based I)” a treaming pull model. Because of this, you can chain several transforms together.

Y’Ju could even apply a custom reader between transforms if needed. This aHows a great deal of flexibility in design.

Transforming XML

The first example you look at takes the books. xm1 document and transforms it into a simple HTML document forJisplay using the XSLT file books. xs l  (This code is in the XSLSample folder.) You will need to add the following using statements:

using System.IO;
using System.Xm1.Xs1;
using System.Xm1.XPath;
The following is the code to perform the transform:
private void buttonl_C1ick(object sender, EventArgs e)
(
Xs1Compi1edTransform trans ~ new Xs1CompiledTransform();
trans.Load(‘books.xs1’);
trans.Transform(‘books.xml’, ‘out.html’);
webBrowserl.Navigate(AppDomain.CurrentDonlain.BaseDirectory + ‘out.html’);

A transform doesn’t get any simpler than this. First, a new XmlCompiledTransform object is created, It loads the books. xsl transform document and then performs the transform. In this example, a string with the file name is used as the input. The output is out .html. This file is then loaded into the Web browser control used on the form. Instead of the file name books. xml as the input document, you can also use an IXPathNavigator based object, This would be any object that can create an XPathNavigator, After the XmlCompiledTransform object is created and the stylesheet is loaded, the transform is performed. The Transform method can take just about any combination of IXPathNavigator obtjects, Streams, TextWriters, XmlWriters, and URIs as parameters. This allows a great deal of flexibility on transform flow.

You can pass the output of one transform ui as the input to the next transform. \
XsltArgumentLists and Xm1Reso1ver objects are also included in the parameter options, We look at the Xs1 tArgumentList object in the next section. XmlReso1 ver-based objects are used to resolve items that are external to the current document. This could be things such as schemas, credentials and, of course, stylesheets, The books. xsl document is a fairly straightforward stylesheet, The document looks like this:

Using XsltArgumentList
XsI tArgumentList isa way thatyou can bind an objectwith methods toa namespace. Once this is done, you can invoke the methods during the transform.Here’s an example:

private void button3_Click(object sender, EventArgs e) ( .
//new XPathDocument
XPathDocument doc = new XPathDocument(“books.xml”);
//new XslTransform
XslCompiledTransform trans a new XslCompiledTransform();
trans.Load(“booksarg.xsl”);
//new XmlTextWriter since we are creating a new xml document
XmIWriter xw = new XmITextWriter(“argSample.xml”, null);
//create the XsIArgumentList and new BookUtils object
XsltArgumentList argBook = new XsltArgumentList();
BookUtils bu = new BookUtils();
//thi~tells the argumentlist about BookUtils
argBook.AddExtensionObject(“urn:XsISample”, bu);
//new XPathNavigator
XPathNavigator nav = doc.CreateNavigator();
//do the transform
trans.Transform(nav, arg~ook, xw);
xw.Close ();
webBrowserl.Navigate(AppDomain.CurrentDomain.BaseDirectory + “argsampie.xml”);

The following isthe code forthe BooksUtil class. This isthe classthatwillbe calledfrom the transform:
class BookUtils
(
public BookUtils() { }
public string ShowText()
( return “This came from the ShowText method!”;
, )
} t
The following is what the output of the transform looks like;the output has been formatted for easier
viewing (argSampIe. XIIIl): –
<books> •
<discbook>
<booktitle>The Autobiography of Benjamin FrankIin</booktitle>
<showtext>This came from the ShowText method!</showtext>
.)

</discbook>
<discbook>
<booktitle>The Confidence Man</booktitle>
<showtext>This came from the ShowText method!</showtext>
• </discbook>
<discbook>
<booktitle>The Gorgias</booktitle>
<showtext>This came from the Sho~~ext method!</showtext>
</discbook>
<discbook>
<booktitle>The Great Cookie Caper</booktitle>
<showtext>This came from the ShowText method!</showtext>
</discbook>
<discbook>
<booktitle>A Really Great Book</booktitle>
<showtext>This came from the ShowText method!</showtext>
</discbook>
</books>

In thisexample, you define a new class,BookUtils. In thisclass,you have one rather useless method
that returns the string This carne from the ShowText method! In the button3_Click () event, you
create the XPathDocument and XslTransform objeQi.Jn a previous example, you loaded the XML’
document and thE!transform document directlyinto the XslCompiledTransform object.This time,
you will use the XPathNavigator to load the documents.
Next, you need to do the following:
XsltArgumentList argBook=new XsltArgume~tList();
BookUtils bu=new BookUtils();
argBook.AddExtensionObject(“urn:XslSample”,bu);
.
This iswhere you create the XsltArgumentList object.You create an instance of the BookUtils object, and when you callthe AddExtensionObj ect () method, you pass in a namespace for your extension and the object that you want to be able to callmethods from. When you make the Transform () call,you pass in the xsl tArgumentList (argBook) along with the XPathNavigator and the XmlWri ter object
you made. The following isthe booksarg .xsl document (based on books. xsl):

<xsl:stylesheet version=”l.O” xmlns:xsl=”http://www.w3.org/1999/XSL/Transform”
xmlns:bookUtil=”urn:XslSample”>
<xsl:output method=”xml” indent=”yes”/>
<xsl:template match=”/”>
<xsl:element name=”books”>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match=”bookstore”>
<xsl:apply-templates select=”book”/>
</xsl:template>
<xsl:template match=”book”>
<xsl:element name=”discbook”>
<xsl:element name=”booktitle”>

<xsl:value-of select=’title’/>
</xsl:element>
<xsl:element name=’showtext’>
<xsl:value-of select=’bookUtil:ShowText()’/>
</xsl:element>
</xsl: element>
</xsl:template>
</xsl:stylesheet>

The two important new linesare highlighted.First,you add the namespace thatyou created when you added the objecttoXsl tArgumentList. Then when you want to make the method call,you use standard XSLT namespace prefixingsyntax and make the method call, Another way you could have accomplished thisiswith XSLT scripting.You can include C#, Visual Basic, and JavaScriptcode in the stylesheet.The great thing about thisisthatunlike current non-.NET implementations, the scriptiscompiled at the Xsl Transform. Load () call;thisway, you are executing
already compiled scripts.

Go ahead and modify the previous XSLT filein thisway. First,you add the scriptto the stylesheet, You can see the following changes in books script .xsl:

<xsl:stylesheet version=’l.0′ xmlns.xsl=’http://www.w3.org/1999/XSL/Transform’
xmlns:msxsl=’urn:schema·s-microsoft-com:xsl·t’
xmlns:user=.http://wrox.com.>
)
</msxsl:script>
<xsl:output method=’xml’ indent=’yes’/>
<xsl:template match=’/’>
<xsl:element name=’books’>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match=’bookstore’>
<xsl:apply-templates select=’book’/>
</xsl:template>
<xsl:template match=’book’>
<xsl:element name=’discbook”>
<xsl:element name=’booktitle’>
<xsl:value-of select=”title’/>
</xsl:element>
<xsl:element name=’showtext’>
• <xsl:value-of select=’user:ShowText()’/>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
<msxsl:script language=”C” implements-prefix=’user”>
string ShowText()
{return -This came from the ShowText method!-;

Once again, the changes are highlighted. You set the scripting namespace, add the code (which was  copied and pasted in from the Visual Studio .NET IDE), and make the call in the stylesheet.

The output looks the same as that of the previous example.
Debugging XSLT

Visual Studio 2008 has the capability to debug transforms. Youcan actually step through a transform line by line, inspect variables, acce;s the call stack, and set break points just like you were debugging C# source code. Youcan debug a transform in two ways: by just using the stylesheet and input XMLfile or by running the application that the transform belongs to. Debugging Without the Application When you first start creating the transforms, sometimes you-don’t really want to run through the entire application, Youjust want to get a stylesheet working. Visual Studio 2008 allows you to do this using the XSLTeditor, Load the books. xsl stylesheet into the Visual Studio 2008XSLTeditor. Set a break point on the following line:
<xsl:value-of select=’title’/>
No!” select the XMLmenu and then Debug XSLT.Youwill be asked for the input XMLdocument. This is
the XMLthat you will want transformed. Now under the default configuration the next thing you will
see is in Figure 28-4.

Figure 28-4

Figure 28-4

Now that the transform has been paused, you can explore almost all of the same debug information you can when debugging source code. Notice that the debugger is showing you the XSLT,the output document with the current element highlighted and the output of the transform. Now you can step through the transform line by line. H your XSLThad any scripting, you could also set breakpoints in the scripts and have the same debugging experience.

Debugging with the Application

If you want to debug a transform and the application at the same time, then you will have to make one small changewhen you create the XsICompiledTransform object. The constructor has an overload that takes a Boolean as a parameter, This parameter is enableDebug. The default is false, which means that even if you have a breakpoint set in the transform, if you run the application code that calls the transform, it will not break. H you set the parameter to true, the debug information for the CSLT is generated and the break point will be hit. So in the previous example: the line of code that created the XlsCompiledTransform would change to this.

XsICompiledTransform trans = new XsICompiledTransform(true);

Now when the application is run in debug mode, even the XSLT will have debug information and you will again have the full VisualStudio debugging experience in your stylesheets, To summarize, the key thing to keep in mind when performing transforms is to remember to use the proper XMLdata store. Use XPathDocument if you don’t need editing capabilities, XmlDataDocument if you’re getting your data from ADO.NET,and XmlDocument if you need to be able to edit the data, In each case, you are dealing with the same process.

Posted on October 31, 2015 in Manipulating XML

Share the Story

Back to Top