7           XML集成(XML Integration)
.NET 语言级集成查询 for XML(XLinq)允许 XML 数据能够通过使用标准查询操作符(standard query operators)就像树形的操作符(tree-specific operators)一样来查询,它能够提供类似 XPath 的导航(XPath-like navigation)在后代(descendants),祖先(ancestors)和兄弟姐妹(siblings)的XML元素中导航。它为 XML 提供一个有效率的内存中的表现(an efficient in-memory representation),它与现有的(existing)System.Xml reader/writer 的基础设施(infrastructure)相结合(integrates with),它比 W3C DOM 更容易使用。有三个类型在集成 XML 和查询中(integrating XML with queries)做了大部分工作:XName,XElement 和XAttribute。
 
XName 提供一个有用的途径来(an easy to use way to)处理命名空间资格的标识符(the namespace-qualified identifiers)(QNames),使用来作为元素(element)和属性(attribute)两个名字。XName 明显地(transparently)控制(handle)标识符的有效率的原子操作(the efficient atomization of identifiers),允许使用符号(symbols)或纯文本(plain strings)任何一个,无论一个 QName 是否需要。
 
XML 元素和属性分别(respectively)使用 XElement 和 XAttribute 来表示(represented),XElement 和 XAttribute 支持常规的构造语法(normal construction syntax),允许开发者使用自然的语法(natural syntax)来写 XML 表达式:
 
 var e = new XElement("Person",
var e = new XElement("Person", 
 new XAttribute("CanCode", true),
                     new XAttribute("CanCode", true),
 new XElement("Name", "Loren David"),
                     new XElement("Name", "Loren David"),
 new XElement("Age", 31));
                     new XElement("Age", 31));

 var s = e.ToString();
var s = e.ToString();

 
这段代码符合(corresponds to)下面的 XML:
 
 <Person CanCode="true">
<Person CanCode="true">
 <Name>Loren David</Name>
  <Name>Loren David</Name> 
 <Age>31</Age>
  <Age>31</Age> 
 </Person>
</Person>

 
需要注意的是没有基于 DOM 的工厂模式(DOM-based factory pattern)被需要来创建 XML 表达式,ToString 实现产生出 XML 原文(the textual XML)。XML 元素还能够通过一个已存在的 XmlReader 或者一个字符串文本(string literal)来构建(constructed):
 
 var e2 = XElement.Load(xmlReader);
var e2 = XElement.Load(xmlReader);
 var e1 = XElement.Parse(
var e1 = XElement.Parse(
 @"<Person CanCode='true'>
@"<Person CanCode='true'>
 <Name>Loren David</Name>
  <Name>Loren David</Name>
 <Age>31</Age>
  <Age>31</Age>
 </Person>");
</Person>");

 
XElement 还支持发出 XML 数据(emitting XML),通过使用现有的 XmlWriter 类型。
 
XElement 与查询操作符(query operators)相吻合(dovetails with),允许开发者针对非 XML 信息编写查询,通过在一个 select 语句体内(the body of a select clause)构造 XElements 来产生 XML 结果:
 
 var query = from p in people
var query = from p in people 
 where p.CanCode
            where p.CanCode
 select new XElement("Person",
            select new XElement("Person", 
 new XAttribute("Age", p.Age),
                                  new XAttribute("Age", p.Age),
 p.Name);
                                  p.Name);

 
这个查询返回一个 XElements 序列,为了允许 XElements 在这种查询的结果之外构建,XElement 构造器允许元素序列(sequences of elements)可以像参数(arguments)一样直接传递:
 
 var x = new XElement("People",
var x = new XElement("People",
 from p in people
                  from p in people 
 where p.CanCode
                  where p.CanCode
 select
                  select 
 new XElement("Person",
                    new XElement("Person", 
 new XAttribute("Age", p.Age),
                                   new XAttribute("Age", p.Age),
 p.Name));
                                   p.Name));

 
这个 XML 表达式导致下面的 XML:
 
 <People>
<People>
 <Person Age="11">Allen Frances</Person>
  <Person Age="11">Allen Frances</Person> 
 <Person Age="59">Connor Morgan</Person>
  <Person Age="59">Connor Morgan</Person> 
 </People>
</People>

 
上面的语句有一个直接地转换成 Visual Basic 的方式,然而,Visual Basic 9.0 也支持 XML 文字(literals)的使用,它允许查询表达式通过使用一个声明式的 XML 语法(a declarative XML syntax)直接从 Visual Basic 来表达(expressed)。上面的例子可以用 Visual Basic 来构造如下所示:
 
 Dim x = _
Dim x = _
 <People>
        <People>
 Select <Person Age=(p.Age) >p.Name</Person> _
Select <Person Age=(p.Age) >p.Name</Person> _
 From p In people _
From p In people _
 Where p.CanCode
Where p.CanCode
 </People>
        </People>

 
这个例子到目前为止展示了(so far have shown)构造了使用一个语言级集成查询(a language-integrated query)来构造新的 XML 值。而且XElement 和 XAttribute 类型还简单化了(simplify)信息从 XML 结构中的提取操作(the extraction of information from XML structures)。XElement 提供了访问者方法(accessor methods)来允许查询表达式被应用于传统的 XPath 轴(the traditional XPath axes)。例于,如下的查询从上面展示的 XElements 中分解出刚才的名字:
 
 IEnumerable<string> justNames =
IEnumerable<string> justNames =
 from e in x.Descendants("Person")
    from e in x.Descendants("Person")
 select e.Value;
    select e.Value;

 //justNames = ["Allen Frances", "Connor Morgan"]
//justNames = ["Allen Frances", "Connor Morgan"]

 
为了从 XML 中分解出结构型值(structured values),我们简单地在 select 语句中使用一个对象初始化表达式(an object initializer expression):
 
 IEnumerable<Person> persons =
IEnumerable<Person> persons =
 from e in x.Descendants("Person")
    from e in x.Descendants("Person")

 select new Person
    select new Person  {
{ 
 Name = e.Value,
        Name = e.Value,
 Age = (int)e.Attribute("Age")
        Age = (int)e.Attribute("Age") 
 };
    };

 
注意 XAttribute 和 XElement 都支持外部的 cast 操作符(explicit cast operators)来分解出文本的值(text value)为一个简单的类型(primitive type),为了处理少见的类型(missing data),我们可以简单地 cast 成一个可以为null 的类型(nullable type):
 
 IEnumerable<Person> persons =
IEnumerable<Person> persons =
 from e in x.Descendants("Person")
    from e in x.Descendants("Person")

 select new Person
    select new Person  {
{ 
 Name = e.Value,
        Name = e.Value,
 Age = (int?)e.Attribute("Age") ?? 21
        Age = (int?)e.Attribute("Age") ?? 21
 };
    };

 
在这个例子中,我们使用一个缺省数值 21,当 Age 属性不存在时。
 
Visual Basic 9.0 为元素(Element),属性(Attribute),和 XElement 的后代访问者方法(Descendants accessor methods)提供直接的语言支持(direct language support),允许基于 XML 的数据(XML-based data)通过使用一个更加合适直接的语法(more compact, direct syntax)来访问。我们可以使用这种功能特性(functionality)来编写前叙的 C# 语句如下所示:
 
 Dim persons = _
Dim persons = _

 Select new Person
    Select new Person  {
{
 .Name = e.Name
      .Name = e.Name
 .Age = e.@Age ?? 21
      .Age = e.@Age ?? 21
 }
      } 
 From e In x
    From e In x Person
Person

 
在 Visual Basic 里,表达式 e.Name 通过名字 Name 来找出所有的 XElements,表达式 e.@Age 通过名字 Age 来找出 XAttribute,当表达式 x...Person 通过名字 Person 来获取 x 的后代集合容器(Descendants collection)中所有的 items。
 
8           总结(Summary)
.NET 语言级集成查询(.NET Language Integrated Query)给 CLR 和语言添加了查询能力(query capabilities),它们以此为目标。查询技巧(facility)建立在 lambda 表达式和表达式树基础之上,允许断言(predicates),映射(projections),和关键词分解(key extraction)表达式用来作为不透明的可执行的代码(opaque executable code)或作为透明的内存中的数据(transparent in-memory data)适合下游的处理和转换(downstream processing or translation)。通过 LINQ 项目定义的标准查询操作符(standard query operators)工作在任何基于 IEnumerable<T> 接口的信息源(IEnumerable<T>-based information source),并且与 ADO.NET(DLinq)和 System.xml(XLinq)相结合来允许关系型(relational)的和 XML 数据来获得语言级集成查询(language integrated query)的好处。
 
 
 
 
全文完, 错误难免,请批评指正,译者Naven 2005-10-30