当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > LINQ学习笔记:导航和查询X-DOM

ASP.NET
使用函数传递参数来执行相应的数据库操作
如何实现在窗体和窗体之间进行传递数据
ASP.NET中文显示之两种解决方法
ASP.NET、JSP及PHP之间的抉择
ASP.NET 2.0发送电子邮件中存在的问题
谈谈HtmlControl与WebControl的区别与用途
从ASP.NET 1.1升级到ASP.NET 2.0要考虑的Cookie问题
通过系统配置来提高ASP.NET应用程序的稳定性
妙用ASP2.0中的URL映射改变网址
AJAX实现web页面中级联菜单的设计
ASP.NET跨页面传值技巧总结
再议ASP.NET DataGrid控件中的“添加新行”功能
Geometry 对象浅析
重构CollapsibleSplitter
如何利用.NET Framework使用RSS feed
ASP.NET获取IP与MAC地址的方法
在ASP.NET 2.0中使用样式、主题和皮肤
ASP.NET中为GridView添加删除提示框
ASP.NET 2.0,无刷新页面新境界
看看一个.net版对话框控件

ASP.NET 中的 LINQ学习笔记:导航和查询X-DOM


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-28   浏览: 54 ::
收藏到网摘: n/a

导航/查询X-DOM

就像你可能期望的那样, XNode和XContainer类定义了方法和属性来测量X-DOM树. 与常规的DOM不同的是, 这些函数并不会返回实现了IList<T>的集合, 而是返回了一个单一值或者一个实现了IEnumerable<T>的序列. 基于这个你可以执行一个LINQ查询或者使用foreach来做枚举. 这同时也允许你使用熟悉的LINQ查询语法来执行简单的导航任务或者高级查询.

在X-DOM中, 元素和属性名都是大小写敏感的, 这与XML是一致的.

FirstNode, LastNode与Nodes

FirstNode与LastNode允许你直接访问第一个或者最后一个子节点; Nodes返回所有的子节点并形成一个序列. 这三个方法只用于直系的后代节点.

检索元素

Elements方法返回类型为XElement的子节点. 例如:

 1: var bench = new XElement ("bench",
 2: new XElement ("toolbox",
 3: new XElement ("handtool", "Hammer"),
 4: new XElement ("handtool", "Rasp")
 5: ),
 6: new XElement ("toolbox",
 7: new XElement ("handtool", "Saw"),
 8: new XElement ("powertool", "Nailgun")
 9: ),
 10: new XComment ("Careful with the nailgun")
 11: );
 12:
 13: foreach (XElement e in bench.Elements( ))
 14: Console.WriteLine (e.Name + "=" + e.Value);
 15:
 16: // 结果: toolbox=HammerRasp
 17: toolbox=SawNailgun

以下的LINQ查询用于查询包含nail gun的toolbox:

 1: IEnumerable<string> query =
 2: from toolbox in bench.Elements( )
 3: where toolbox.Elements( ).Any
 4: (tool => tool.Value == "Nailgun")
 5: select toolbox.Value;
 6:
 7: RESULT: { "SawNailgun" }

Elements等价于Nodes上面的LINQ查询, 我们之前的查询也可以被写为:

 1: from toolbox in bench.Nodes().OfType<XElement>()
 2: where ...

接下来的例子使用一个SelectMany查询检索hand tools:

 1: IEnumerable<string> query =
 2: from toolbox in bench.Elements( )
 3: from tool in toolbox.Elements( )
 4: where tool.Name == "handtool"
 5: select tool.Value;
 6:
 7: RESULT: { "Hammer", "Rasp", "Saw" }

Elements也可以只返回给定名称的元素, 例如:

 1: int x = bench.Elements ("toolbox").Count(); // 2

这等价于:

 1: int x = bench.Elements()
 2: .Where (e => e.Name == "toolbox")
 3: .Count(); // 2
 4:

Elements还定义了一个扩展方法接受IEnumerable<XContainer>参数. 更精确的说, 它接受了此种类型的参数:

 1: IEnumerable<T> where T : XContainer

这让其可以和元素序列一起工作, 使用这个方法我们可以重写查找hand tools的查询:

 1: from tool in bench.Elements ("toolbox")
 2: .Elements ("handtool")
 3: select tool.Value.ToUpper( );

第一个Elements绑定到XContainer上, 第二个则绑定到扩展方法上.

读取一个单一的元素

方法Element(单数)返回匹配给定名称的第一个元素. Element对于简单的导航是非常有用的, 例如:

 1: var settings = XElement.Load ("databaseSettings.xml");
 2:
 3: string cx = settings.Element ("database")
 4: .Element ("connectString")
 5: .Value;

Element的作用相当于调用Elements然后再应用LINQ的FirstOrDefault并给定一个名称作为匹配断言. 如果没有任何元素匹配到, 则Element返回null.

如果元素xyz不存在, 那么Element(”xyz”).Value将会抛出一个NullReferenceException异常. 如果你倾向于使用null代替异常, 可以将XElement转换成string而不是调用它的Value属性, 如下:

 1: string xyz =
 2: (string) settings.Element("xyz");

XElement定义了一个显示的string转换正式为了这个目的.

递归功能

XContainer同时也定义了Descendants和DescendantNodes方法, 它们递归地返回子元素或者子节点.Descendant接受一个可选的元素名, 会到我们之前的例子, 我们可以使用Descendants去查找所有的hand tools:

 1: Console.WriteLine
 2: (bench.Descendants ("handtool").Count( )); // 3

不管是父节点还是叶节点都包含在整体横切中. 以下的查询取得所有包含单词”careful”, 存在于X-DOM任何地方的注释节点:

 1: IEnumerable<string> query =
 2: from c in bench.DescendantNodes( ).OfType<XComment>( )
 3: where c.Value.Contains ("careful")
 4: orderby c.Value
 5: select c.Value;

查询父节点

所有的XNodes都有一个Parent属性和AncestorXX的方法用于父节点导航. 一个父亲节点永远是一个XElement.

如果x是一个XElement, 以下代码打印true:

 1: foreach (XNode child in x.Nodes( ))
 2: Console.WriteLine (child.Parent == x);

如果x是一个XDocument的话, XDocument有点独特, 它永远不能作为任何节点的父亲节点. 为了访问XDocument,应该使用Document属性, 这只争对X-DOM树上的任意对象可以工作.

Ancestors返回一个序列其第一个元素是Parent, 下一个元素则是Parent.Parent, 依次类推直到根元素.

你还可以使用LINQ查询AncestorsAndSelf().Last()来取得输入序列的根元素. 另外一种方法是调用Document.Root, 但只有当XDocument呈现的时候才能工作.

对等节点导航

使用PreviousNode和NextNode(FirstNode / LastNode),我们可以使用一个linked list横贯所有的节点. 这并不是巧合, 在内部, Nodes实际上就是存储在一个linked list.

属性导航

XAttributes定义了PreviousAttribute和NextAttribute, Parent也是一样.

Attributes方法接受了一个名称并返回包含0或1个元素的序列; 在XML中, 一个元素不能包含重复的属性名.

待续!