When working with XML data we inevitably have to concern ourselves with XML namespaces + XML namespace prefixes. The Linq to XML API has been designed to make dealing with namespaces and namespaces prefixes as direct and straightforward as possible. Rather than having to deal with XmlNamespaceManagers and the like we simple reference all of our elements and attributes using their fully expanded name (namespace + local name).
While the simplification provided by Linq to XML makes dealing with namespaces slightly more straightforward it doesn't go as far as I think it needs to. We still need to remember to include our namespaces in every query we perform. When working with XML trees that only contain one default namespace I'd like something simpler. Enter the XNamespaceScope class. The XNamespaceScope class would be used similar to how we make use of the TransactionScope class for managing transactions. When we're about to work with an XML tree that only contains one namespace which we're interested in we can new up a XNamespaceScope class, place it inside a using block that surrounds our query expressions, and have Linq to XML use the XNamespace that's passed to the XNamespaceScope in all queries within the block. So rather than this code where we have to repeatedly include our namespace (ns)
1 XNamespace ns = "http://webservices.amazon.com/AWSECommerceService/2005-10-05";
2 var booksToImport =
3 from amazonItem in amazonXml.Descendants(ns + "Item")
4 let attributes = amazonItem.Element(ns + "ItemAttributes")
5 select new Book {
6 Isbn=(string) attributes.Element(ns + "ISBN"),
7 Title=(string) attributes.Element(ns + "Title"),
8 PubDate=(DateTime) attributes.Element(ns + "PublicationDate"),
9 Price=ParsePrice(attributes.Element(ns + "ListPrice")),
10 BookAuthors=GetAuthors(attributes.Elements(ns + "Author"))
11 };
We instead do:
1 XNamespace ns = "http://webservices.amazon.com/AWSECommerceService/2005-10-05";
2 using(new XNamespaceScope(ns)) {
3 var booksToImport =
4 from amazonItem in amazonXml.Descendants("Item")
5 let attributes = amazonItem.Element("ItemAttributes")
6 select new Book {
7 Isbn=(string) attributes.Element("ISBN"),
8 Title=(string) attributes.Element("Title"),
9 PubDate=(DateTime) attributes.Element("PublicationDate"),
10 Price=ParsePrice(attributes.Element("ListPrice")),
11 BookAuthors=GetAuthors(attributes.Elements("Author"))
12 };
13 }
Thoughts?
tags: linq, xlinq, linqtoxml