這幾天抽空看了看C# 3.0的一些新特性,匿名對象、Lambda表達式、Linq等 ,給我很大的沖擊。簡潔化、人性化、更加可讀易理解的代碼,讓C# 3.0增色不 少。以前我總認為C#語言就是follow Java語言,現在看來微軟就是強大,在流 行的基礎上創出了自己的個性,漂亮簡潔高效的編程語言讓人不得不傾心。
因為以前的項目用到Xml操作比較多,我著重看了看Linq To Xml,用 msdn上的話來說,Linq To Xml是LINQ項目的一個組件,它是一種現代化的、在 內存中的XML編程API,吸取了最新的.NET框架語言創新的優點(比如使用泛型、 可空類型),它提供全新的、輕量的、高效的API操作。有興趣的人可以參考這 篇文章:.NET language-Integrated Query for XML Data。 下面看看它到底有 哪些吸引人之處。
如果我們要生成這樣一種XML:
<people>
<person>
<firstname>Bob</firstname>
<lastname>Willam</lastname>
<age>50</age>
<phone type="mobile">012345</phone>
<phone type="home">987654</phone>
<address>
<country>USA</country>
<city>LA</city>
</address>
</person>
....
</people>
使 用XmlDocument來生成這樣一段XML數據,大概是下面這樣:
XmlDocument doc = new XmlDocument();
XmlElement firstname = doc.CreateElement("firstname");
firstname.InnerText = "Bob";
XmlElement lastname = doc.CreateElement("lastname");
lastname.InnerText = "Willam";
XmlElement age = doc.CreateElement ("age");
age.InnerText = "50";
XmlElement phone1 = doc.CreateElement("phone");
phone1.SetAttribute("type", "mobile");
phone1.InnerText = "012345";
XmlElement phone2 = doc.CreateElement("phone");
phone2.SetAttribute ("type", "home");
phone2.InnerText = "987654";
XmlElement country = doc.CreateElement ("country");
country.InnerText = "USA";
XmlElement city = doc.CreateElement("city");
city.InnerText = "LA";
XmlElement address = doc.CreateElement("address");
address.AppendChild (country);
address.AppendChild(city);
XmlElement person = doc.CreateElement("person");
person.AppendChild (firstname);
person.AppendChild(lastname);
person.AppendChild(age);
person.AppendChild(phone1);
person.AppendChild(phone2);
person.AppendChild(address);
XmlElement people = doc.CreateElement("people");
people.AppendChild(person);
doc.AppendChild (people);
這段代碼看上去雜亂無章,看久了頭暈,毫無美觀可 言。一般情況下會對XmlDocument的API進行封裝,減少重復代碼:
XmlElement firstname = XmlUtility.MakeElement(doc, "firstname", "Bob");
XmlElement lastname = XmlUtility.MakeElement(doc, "lastname", "Willam");
...
XmlElement address = XmlUtility.MakeElement(doc, "address",
XmlUtility.MakeElement(doc, "country", "USA"),
XmlUtility.MakeElement(doc, "city", "LA"));
public class XmlUtility
....
public static XmlElement MakeElement(XmlDocument doc, string key, string value)
{
XmlElement e = doc.CreateElement(key);
e.InnerText = value;
return e;
}
public static XmlElement MakeElement(XmlDocument doc, string key, params XmlElement[] values)
{
XmlElement e = doc.CreateElement(key);
foreach(XmlElement value in values)
e.AppendChild(value);
return e;
}
下面看看怎樣用Linq To Xml操作API來生成這樣一段Xml 數據(需要引用System.Xml.Linq程序集):
XElement people =
new XElement("people",
new XElement("person",
new XElement("firstname", "Bob"),
new XElement("lastname", "Willam"),
new XElement("age", "50"),
new XElement("phone", "012345",
new XAttribute("type", "mobile")),
new XElement("phone", "987654",
new XAttribute("type", "home")),
new XElement("address",
new XElement("country", "USA"),
new XElement("city", "LA")
)
)
);
這樣的代碼簡潔直觀,構造方法加上良好的縮進 ,讓人可以很容易看懂該Xml的結構層次。
用上Linq以後,查詢Xml也很 簡單,比如:
XDocument doc = XDocument.Load (@"peopleData.xml");
var foundPeople = doc.Descendants("person")
.Where(p => Convert.ToInt32(p.Element ("age").Value) > 20)
.Select(p => new
{
Name = p.Element ("firstname").Value + " "
+ p.Element ("lastname").Value,
Age = Convert.ToInt32 (p.Element("age").Value),
Phone = p.Elements ("phone").Select(ph => ph.Value).ToArray(),
}
);
foreach (var person in foundPeople)
{
//person.Name
//person.Age
//person.Phone....
}
我們再來看看Linq To Xml是怎樣加載Xml呢?
在c# 2.0裡面加載Xml數據都是通過XmlDocument來操作,比如:
string xmlContent = "...";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlContent);
或者從文件中加載:
xmlDoc.Load(@"D:\test.xml");
而Linq To Xml摒棄了必須利用Document操作,可以直接用XElement的Load或Parse方法
string xmlContent = "...";
XElement xmlFromString = XElement.Parse(xmlContent);
或者
XElement xmlFromFile = XElement.Load (@"D:\test.xml");//當然Load有多個重載方法,比如從Reader中加載 等等
Linq To Xml提供了簡潔並且人性化的API,使得程序員對XML 元素 的操作更加直觀、自然,最大的改變是摒棄了通過XmlDocument操作XML 元素, 在2.0及以前的時代,XML document是作為XML文檔樹的容器而存在的,XML的各 種節點,包括Element,Attribute等都必須通過XML document的上下文來創建:
XmlDocument xmlDoc = new XmlDocument();
XmlElement person = xmlDoc.CreateElement("person");
XmlAttribute att = xmlDoc.CreateAttribute ("age");
通過XML document上下文創建的元素等只能 存在於該上下文中,如果另外一個XML document想要使用這些元素,必須 ImportNode,在Linq To Xml中沒有這樣煩瑣的操作和注意事項,一切都是以最 自然最人性化的方式進行:
XElement person = new XElement ("person");
XAttribute age = new XAttribute ("age","50");
這裡並沒有提供 XAttribute(string name)的構造函數,恐怕是考慮到Attribute必須有值吧,才 給了這個約束。
當然,如果有需要的話,在Linq To Xml中也可以使用 XML Document,比如在XML document中需要添加聲明等等。
XDocument xmlDoc =
new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XComment("This is the comments"),
new XProcessingInstruction("test", "test processing instruction"),
new XElement("people")
);