XLINQ to XML support in VB9
I started out as a VB guy and spent many years there. However, my love affair with Dim As waned in the last several years and I became a C# guy. Anders is awesome, and the stuff he and his team is doing in C# 3.0 is shiny to say the least. I thought of VB as the Red-headed stepchild of the family. I may have even said things like "what's the point?" but you'll never get me to admit it.
However, I have to say that I'm really impressed with the LINQ to XML stuff in Orcas, to the point where I'd consider writing a library with VB9 just to get this syntax. It's syntactic sugar, to be clear (what isn't, really?) but it's nice enough that it really makes working with XML in VB a pleasure.
Here's a simple example I'm working on...
In C#, using an XmlReader (Yes, I know there are other ways, like XPath, so relax, it's an example), a person wants to count books in an books.xml file very quickly:
int bookcount = 0; XmlReaderSettings settings = new XmlReaderSettings(); NameTable nt = new NameTable(); object book = nt.Add("book"); settings.NameTable = nt; settings.IgnoreWhitespace = true; settings.IgnoreComments = true; string booksFile = Path.Combine(Request.PhysicalApplicationPath, "books.xml"); using (XmlReader reader = XmlReader.Create(booksFile, settings)) { while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element && book.Equals(reader.LocalName)) //A subtle, but significant change! { bookcount++; } } } Response.Write(String.Format("Found {0} books!", bookcount));
Then you might do something like this to collect the titles of those books and count them, again in C# but now using LINQ to XML:
XDocument booksXML = XDocument.Load(Server.MapPath("books.xml")); var books = from book in booksXML.Descendants("{http://example.books.com}book") select book.Element("{http://example.books.com}title").Value; Response.Write(String.Format("Found {0} books!", books.Count()));
And that's cool, but here's the same code in VB:
Dim booksXML = XDocument.Load(Server.MapPath("books.xml")) Dim books = From book In booksXML...<b:book> Select book.<b:title>.Value Response.Write(String.Format("Found {0} books!", books.Count()))
Notice the syntax around the From statement on the second line. That cool namespace shortcut came from an Imports statement that declared the use of the Xml Namespace, and the prefix. Notice that ... and . are used for the calls to Descendants and Element respectively.
Imports System.Xml.Linq Imports <xmlns:b="http://example.books.com">
Crazy. Now, let me get some actual objects out of this document. Assume I have an Author class around here.
XDocument booksXML = XDocument.Load(Server.MapPath("books.xml")); var authors = from book in booksXML.Descendants("{http://example.books.com}author") select new Author { FirstName = book.Element("{http://example.books.com}first-name").Value, LastName = book.Element("{http://example.books.com}last-name").Value }; foreach (Author a in authors) { Response.Write(String.Format("Author: {1}, {0}<BR/>", a.FirstName, a.LastName)); }
Notice the select new Author statement. I could also have used an anonymous type if I'd liked also. Here's the same in VB:
Dim booksXML = XDocument.Load(Server.MapPath("books.xml")) Dim authors = From book In booksXML...<books:book> Select New Author _ With {.FirstName = book.<books:author>.<books:first-name>.Value, _ .LastName = book.<books:author>.<books:last-name>.Value} For Each a As Author In authors Response.Write(String.Format("Author: {1}, {0}<BR/>", a.FirstName, a.LastName)) Next
I really like this syntax...LINQ is turning out to not be as scary as I thought. You'll see these examples in a book someday.
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter
XNamespace ns = "http://example.books.com";
Then use it like this:
var authors = from book in booksXML.Descendants( ns + "author" ) ...
Not as nice, but better.
Anyhow, VB's line continuation _
still _
sucks _
a big one _
and most especially for multi-line LINQ statements.
In VB:
Dim q = From p In db.Products _
Select p.ProductID, p.ProductName, p.UnitPrice _
Skip 20 _
Take 20
In C#:
var q = from p in db.Products
select p.ProductID, p.ProductName, p.UnitPrice;
q = q.Skip(20).Take(20);
Comments are closed.
Also, you don't have to use the fully qualified name in C#. You can use this syntax:
XNamespace ns = "http://example.books.com";
var authors = from book in booksXML.Descendants(ns +"author")
select new Author
{
FirstName = book.Element(ns + "first-name").Value,
LastName = book.Element(ns + "last-name").Value
};
Don Demsak