Monday, September 28, 2009

Just a prefix issue

Everybody who has to deal with XML and XPath in .NET just Run into an issue of accessing elements without having any prefix for the default namespace.

Assume a sample:
You've got an XML-File books.xml as follows:
<books xmlns="urn:books">
 <book>
  <author>It's just me</author>
  <publisheddate>2009-09-25T09:06</publisheddate>
 </book>
</books>

And now? How to access a node?

First attempt:
XmlDocument doc = new XmlDocument();
doc.Load("books.xml");
 
// just build xPath for testing
StringBuilder xPath = new StringBuilder();
XmlNode someNode = doc.DocumentElement.FirstChild.FirstChild;
 
do
{
   xPath.Insert(0, someNode.LocalName);
   xPath.Insert(0, "/");
   someNode = someNode.ParentNode;
}
while (someNode != null && someNode.NodeType != XmlNodeType.Document);
 
// xPath == "/books/book/author"
XmlNode author = doc.DocumentElement.SelectSingleNode(xPath.ToString());

What is the value of author? Right, it's null, hu.

Next attempt, try using XmlNamespaceManager.
XmlNamespaceManager manager = new XmlNamespaceManager(doc.NameTable);
// try to access with XmlNamespaceManager
XmlNode author = doc.DocumentElement.SelectSingleNode(xPath.ToString(), manager);

What is the value of author? Right, it's still null, hu.

And now?

Try to explain: The Namespace and the Prefix of the used namespace is not defined so xpath could not be resolved.

So try this:
XmlNamespaceManager manager = new XmlNamespaceManager(doc.NameTable);
// try to access with XmlNamespaceManager
XmlNode author = doc.DocumentElement.SelectSingleNode(xPath.ToString(), manager);

So try this:
string prefix = "mySample";
if (String.IsNullOrEmpty(manager.LookupPrefix(doc.DocumentElement.NamespaceURI)))
{
   // namespace not added
   manager.AddNamespace(prefix, doc.DocumentElement.NamespaceURI);
}
 
// injecting the namespace
xPath.Replace("/", String.Format("/{0}:", prefix));
 
// xPath is now  "/{mySample}:books/{mySample}:book/{mySample}:author"
author = doc.DocumentElement.SelectSingleNode(xPath.ToString(), manager);

And now, author sould be the selected node.

Thursday, September 10, 2009

Keep clean with temporary files

Every developer runs into a situation where temporary files are needed. In cause of an error, many developers forget to clean up this garbage within the temporary files directory. And I HATE that.

So therefore here is an hint for C# developers:
Just use the
FileOptions.DeleteOnClose
value as parameter of the
FileStream
constructor, this will keep you handles clean.

Heres comes an excample:
using (FileStream fStream = new FileStream(Path.GetTempFileName(), FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.DeleteOnClose)))
{
// do work
}

Good luck.

Exchange variables for experts - or these who want to be

To show how cool you could code, you can use the following snippet to impress your girlfriend 8)

estimating x and y are integers
x = x ^ y;
y = y ^ x;
x = x ^ y;

shorter
x ^= y;
y ^= x;
x ^= y;

and a one liner if you like sunglasses
x ^=  y; y ^=  x; x ^=  y;

Cool as ice ...