XML Tree functional construction is a great stuff and definitely a big improvement over the upside down DOM-style XML building. I only wanted to note that one doesn't have to wait years for C# 3.0 to be able to build XML tree in a natural top-down way, that was actually possible from the very beginning (here is .NET 2.0 sample, in .NET 1.X one would need XmlNodeWriter):
XmlDocument doc = new XmlDocument();
XmlWriter w = doc.CreateNavigator().AppendChild();
w.WriteStartElement("contacts");
w.WriteStartElement("contact");
w.WriteElementString("name", "Patrick Hines");
w.WriteStartElement("phone");
w.WriteAttributeString("type", "home");
w.WriteString("206-555-0144");
w.WriteEndElement();
w.WriteStartElement("phone");
w.WriteAttributeString("type", "work");
w.WriteString("425-555-0145");
w.WriteEndElement();
w.WriteStartElement("address");
w.WriteElementString("street1", "123 Main St");
w.WriteElementString("city", "Mercer Island");
w.WriteElementString("state", "WA");
w.WriteElementString("postal", "68042");
w.WriteEndElement();
w.WriteEndElement();
w.WriteEndElement();
w.Close();
Should admit XLinq's functional construction still looks shorter and tree-friendly, but it is seriously constrained to building only XLinq XML tree in-memory. If one day you decide that building in-memory XML tree just to be saved to a disk is a waste of memory (and it is a waste), you would need to rewrite completely XML construction code and that's bad. XmlWriter has no limits here - you can use it for building XML tree in memory or writing XML directly to a stream in a fast efficicent non-caching way. XmlWriter just does its job - writes XML with no coupling to the result and that's way any code that produces XML with XmlWriter is more reusable.
Ergo - please don't repeat System.Xml mistakes and treat XmlWriter as a first class citizen - provide a way to build XDocument/XElement with XmlWriter, that will be good architecturally and will provide smoother migration from XmlDocument v2. E.g. what about providing an editable XPathNavigator over XElement or XDocument?
Update. And as a matter of interest XQuery being truly functional language of course supports functional composition too. Here is a sample:
element book {
attribute isbn {"isbn-0060229357" },
element title { "Harold and the Purple Crayon"},
element author {
element first { "Crockett" },
element last {"Johnson" }
}
}
Looks terribly familiar, huh?
But as Erik pointed out in comments neither form of composition can beat the ultimate way of building XML - literal one. Here is how it looks like in XQuery:
<example>
<p> Here is a query. </p>
<eg> $b/title </eg>
<p> Here is the result of the query. </p>
<eg>{ $b/title }</eg>
</example>
C# doesn't support it yet, while VB sort of does. "Sort of" because VB form of "literal XML" is not actually XML, but confusing ASP-like mess. But I'll address that later.
To be continued...
I hope Microsoft XML Team would consider adding support for xml:id into the next .NET version and into XLinq. That's really valuable addition to the XML Core.
And of course I cannot avoid Canonical XML (C14N) and xml:id controversy. Read Norm for the crux of the issue. In short - Canonical XML is broken. Here is an illustration:
string xml = @"
<foo xml:id=""f42"" xml:base=""http://foo.com"">
<bar xml:base=""dir"">baz
</foo>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlDsigC14NTransform c14n = new XmlDsigC14NTransform();
c14n.LoadInput(doc.SelectNodes("/foo/bar"));
StreamReader sr = new StreamReader((Stream)c14n.GetOutput());
Console.WriteLine(sr.ReadToEnd());
Guess what is the result?
<bar xml:base="dir" xml:id="f42"></bar>Not only xml:id is inherited by bar element (so now you can get different element when searching by the same ID), but xml:base is broken (absolute base URI part is lost). Too bad. Canonical XML should definitely be fixed.