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",
new XAttribute("CanCode", true),
new XElement("Name", "Loren David"),
new XElement("Age", 31));
var s = e.ToString();
这段代码符合(corresponds to)下面的 XML:
<Person CanCode="true">
<Name>Loren David</Name>
<Age>31</Age>
</Person>
需要注意的是没有基于 DOM 的工厂模式(DOM-based factory pattern)被需要来创建 XML 表达式,ToString 实现产生出 XML 原文(the textual XML)。XML 元素还能够通过一个已存在的 XmlReader 或者一个字符串文本(string literal)来构建(constructed):
var e2 = XElement.Load(xmlReader);
var e1 = XElement.Parse(
@"<Person CanCode='true'>
<Name>Loren David</Name>
<Age>31</Age>
</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
where p.CanCode
select new XElement("Person",
new XAttribute("Age", p.Age),
p.Name);
这个查询返回一个 XElements 序列,为了允许 XElements 在这种查询的结果之外构建,XElement 构造器允许元素序列(sequences of elements)可以像参数(arguments)一样直接传递:
var x = new XElement("People",
from p in people
where p.CanCode
select
new XElement("Person",
new XAttribute("Age", p.Age),
p.Name));
这个 XML 表达式导致下面的 XML:
<People>
<Person Age="11">Allen Frances</Person>
<Person Age="59">Connor Morgan</Person>
</People>
上面的语句有一个直接地转换成 Visual Basic 的方式,然而,Visual Basic 9.0 也支持 XML 文字(literals)的使用,它允许查询表达式通过使用一个声明式的 XML 语法(a declarative XML syntax)直接从 Visual Basic 来表达(expressed)。上面的例子可以用 Visual Basic 来构造如下所示:
Dim x = _
<People>
Select <Person Age=(p.Age) >p.Name</Person> _
From p In people _
Where p.CanCode
</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 =
from e in x.Descendants("Person")
select e.Value;
//justNames = ["Allen Frances", "Connor Morgan"]
为了从 XML 中分解出结构型值(structured values),我们简单地在 select 语句中使用一个对象初始化表达式(an object initializer expression):
IEnumerable<Person> persons =
from e in x.Descendants("Person")
select new Person {
Name = e.Value,
Age = (int)e.Attribute("Age")
};
注意 XAttribute 和 XElement 都支持外部的 cast 操作符(explicit cast operators)来分解出文本的值(text value)为一个简单的类型(primitive type),为了处理少见的类型(missing data),我们可以简单地 cast 成一个可以为null 的类型(nullable type):
IEnumerable<Person> persons =
from e in x.Descendants("Person")
select new Person {
Name = e.Value,
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 = _
Select new Person {
.Name = e.Name
.Age = e.@Age ?? 21
}
From e In xPerson
在 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