Sunday, May 06, 2007

LINQ,XML集成(XML Integration)

7           XML集成(XML Integration


.NET 语言级集成查询 for XMLXLinq)允许 XML 数据能够通过使用标准查询操作符(standard query operators)就像树形的操作符(tree-specific operators)一样来查询,它能够提供类似 XPath 的导航(XPath-like navigation)在后代(descendants),祖先(ancestors)和兄弟姐妹(siblings)的XML元素中导航。它为 XML 提供一个有效率的内存中的表现(an efficient in-memory representation),它与现有的(existingSystem.Xml reader/writer 的基础设施(infrastructure)相结合(integrates with),它比 W3C DOM 更容易使用。有三个类型在集成 XML 和查询中(integrating XML with queries)做了大部分工作:XNameXElement 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.NETDLinq)和 System.xmlXLinq)相结合来允许关系型(relational)的和 XML 数据来获得语言级集成查询(language integrated query)的好处。


 


 


 


 


全文完, 错误难免,请批评指正,译者Naven 2005-10-30

No comments: