这几天抽空看了看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")
);

 

 posted on 2007-07-02 13:50  紫色阴影  阅读(2380)  评论(5编辑  收藏  举报
我要啦免费统计