Living .NET...

Musings on .NET, and the like - Manoj G [MVP, Connected Systems Developer]

December 2004 - Posts

Path and Environment: Truly useful classes

I always remember doing painful string manipulations on a file path string, either to extract the drive, the file name or the extension bits from the string in VB6. Things are definitely better in .NET. The System.IO.Path class basically abstracts the way a path string is structured and provides a set of simple helper methods which also absolves a developer from knowing things like the directory separator character, Volume separator character and so on. Saravanaa good friend of mine, explains more on this in his article.

Another really useful class is System.Environment, whichs comes packed with plentiful handy functions to get environment information like environment variables, system directory, etc etc. Check this MSDN link for a complete listing.

Really useful, I must say.

Posted: Dec 16 2004, 02:19 PM by Manoj G | with no comments
Filed under:
Xpath Expressions and XPathNavigator to the rescue

I would like to admit that I have, many a times, taken XML handling for granted and have come with ghastly pieces of code like the one shown below, where all I need is to find out the number of nodes in an Xml document. What I am doing here, is loading the Xml data it to a DOM, creating a node list and then accessing its Count property - all in all, an extremely expensive and needless process.

booksDoc.LoadXml(booksXml);

int numBooks = booksDoc.SelectNodes("bookstore/book").Count;
for (int i = 0; i < numBooks; i++)
{
    
// Some code
}

A much better and more efficient way to solve this problem is to use XPath Expressions and the XPathNavigator class. The XPathNavigator provides a method called Evaluate which can evaluate Xpath expressions to return boolean, string, int values accordingly. As an alternative to the above code, we can just use the count Xpath function to return the number of nodes in the node-set.

XPathDocument xpathDoc = new XPathDocument(reader);
XPathNavigator navigator = xpathDoc.CreateNavigator();

int numBooks = Convert.ToInt32(navigator.Evaluate("count(bookstore/book)"));

for (int i = 0; i < numBooks; i++)
{
    
//Some code
}

The reason why the latter approach is efficient is that XPathDocument creates a read-only in-memory tree that is optimized for Xpath and Xslt. On the other hand, XmlNode is a modifiable DOM representation, which could make it inefficient for Xpath-like scenarios.

An example from Aaron Skonnard's Xml Files column illustrates this better. What the code sample is trying to do is find the sum price of invoice line items from the given Xml document.

The XmlDocument approach:

const string EXPRESSION = "/Invoices/Invoice/LineItems/LineItem/Price/text()";

static void UseDOM()
{
    XmlDocument doc = 
new XmlDocument();
    doc.Load("invoices.xml");

    XmlNodeList selection = doc.SelectNodes(EXPRESSION);
    
double total = 0;

    
foreach (XmlNode n in selection)
    {
        total += XmlConvert.ToDouble(n.InnerText);
    }

    Console.WriteLine("sum: {0}", total);
}

The better approach. Note the usage of the sum Xpath expression.

const string SUMEXPRESSION = "sum(/Invoices/Invoice/LineItems/LineItem/Price/text())";

static void UseNavigatorEvaluate()
{
    XPathDocument doc = 
new XPathDocument("invoices.xml");

    XPathNavigator nav = doc.CreateNavigator();

    Console.WriteLine("sum: {0}", nav.Evaluate(SUMBLOCKED EXPRESSION;

}
Posted: Dec 10 2004, 12:03 PM by Manoj G | with no comments
Filed under: