当前位置: 首页 > 编程日记 > 正文

LINQ之路19:LINQ to XML之X-DOM更新、和Value属性交互

本篇包含两部分内容:X-DOM更新一节中我们会详细讨论LINQ to XML的更新方式,包括Value的更新、子节点和属性的更新、通过Parent节点实现更新;

和Value属性交互一节会详细讨论XElement和XAttribute的Value属性。如果一个元素只有单个XText子节点,那么XElement的Value属性即是对该子节点的快捷方式。对于XAttribute来讲,Value就是指其属性值。X-DOM为XElement和XAttribute的Value属性提供了一致的操作方式。

X-DOM更新

Value更新

成员

目标对象

Value { get; set }

XElement, XAttribute

SetValue (object value)

XElement, XAttribute

SetValue方法把element或attribue的内容替换为给定的简单值。设置Value属性完成相同的工作,但只接受string数据。下一节“和Value交互”详细讨论了这两个成员。

调用SetValue(或设置Value属性)时值得注意的地方是:它会替换所有的子节点/child nodes

            XElement settings = new XElement("settings",
new XElement("timeout", 30)
);
settings.SetValue("XXX"); // SetValue后子节点timeout已经被替换了

Console.WriteLine(settings.ToString());
// Result: <settings>XXX</settings>

更新子节点和属性

类型

成员

目标对象

Add

Add (params object[] content)

XContainer

AddFirst (params object[] content)

XContainer

Remove

RemoveNodes()

XContainer

RemoveAttributes()

XElement

RemoveAll()

XElement

Update

ReplaceNodes (params object[] content)

XContainer

ReplaceAttributes (params object[] content)

XElement

ReplaceAll (params object[] content)

XElement

SetElementValue (XName name, object value)

XElement

SetAttributeValue (XName name, object value)

XElement

上表中最方便的方法是最后两个:SetElementValue 和SetAttributeValue。他们实例化一个XElement或XAttribute,把它加至parent,并替换掉同名的元素或属性:

            XElement settings = new XElement("settings");
settings.SetElementValue("timeout", 30); // 添加子节点
settings.SetElementValue("timeout", 60); // 更新至60

Add方法向element或document对象添加一个子节点。AddFirst完成相同的工作,但是新节点会插入到最前面。

RemoveNodes方法会删除所有的子节点;RemoveAttributes会删除所有的属性;RemoveAll等价于调用这两个方法,同时删除所有子节点和属性。

ReplaceXXX方法等价于先调用Remove再调用Add方法。他们会先行获得输入参数的一个快照(拷贝),所以settings.ReplaceNodes(settings.Nodes());也会按照我们期望的方式工作。

通过Parent节点更新

成员

目标对象

AddBeforeSelf (params object[] content)

XNode

AddAfterSelf (params object[] content)

XNode

Remove()

XNode*, XAttribute*

ReplaceWith (params object[] content)

XNode

上表中的方法AddBeforeSelf、AddAfterSelf、Remove、和ReplaceWith不是用来操作子节点(children)。相反,他们操作当前节点本身所在的集合。这就决定了节点必须有一个父元素,否则将会抛出异常。

AddBeforeSelf和AddAfterSelf根据当前节点的位置来插入一个新节点:

            XElement items = new XElement("items",
new XElement("one"),
new XElement("three")
);
items.FirstNode.AddAfterSelf(new XElement("two"));

Console.WriteLine(items.ToString(SaveOptions.DisableFormatting));
// 结果如下:
<items><one /><two /><three /></items>

像上面这样在任意位置插入一个节点是非常有效的,哪怕是在一个有很多元素的sequence中,原因在于X-DOM中的nodes在内部是以链表的形式实现的。

Remove方法在其parent元素中删除当前节点本身;ReplaceWith完成相同的工作,然后在当前位置插入其他指定的内容。示例如下:

            XElement items = XElement.Parse ("<items><one/><two/><three/></items>");
items.FirstNode.ReplaceWith (new XComment ("One was here"));

// 结果如下:
<items><!--one was here--><two /><three /></items>
删除一个节点或属性sequence

正因为有了System.Xml.Linq中定义的扩展方法,我们可以在一个节点或属性sequence上调用Remove方法,实现一次删除多个节点或属性的功能:

            // 假如我们有如下格式的XElement
XElement contacts = XElement.Parse(
@"<contacts>
<customer name='Mary'/>
<customer name='Chris' archived='true'/>
<supplier name='Susan'>
<phone archived='true'>012345678<!--confidential--></phone>
</supplier>
</contacts>
");

// 下面的查询删除所有的customers:
contacts.Elements ("customer").Remove();

// 下面的代码删除所有archived为true的元素(Chris被删除):
contacts.Elements().Where (e => (bool?) e.Attribute ("archived") == true)
.Remove();

// 如果我们使用Descendants()来替换Elements(),phone元素也会被删除,结果如下:
<contacts>
<customer name="Mary" />
<supplier name="Susan" />
</contacts>

// 下面的示例删除任意位置带有confidential注释的所有元素:
contacts.Elements().Where (e => e.DescendantNodes()
.OfType<XComment>()
.Any (c => c.Value == "confidential")
).Remove();
// 结果如下:
<contacts>
<customer name="Mary" />
<customer name="Chris" archived="true" />
</contacts>

// 与之相比,下面这个这个更简单的查询删除所有的注释元素:
contacts.DescendantNodes().OfType<XComment>().Remove();

和Values属性交互

XElement和XAttribute都有一个string类型的Value属性。如果一个元素只有单个XText子节点,那么XElement的Value属性即是对该子节点的快捷方式。对于XAttribute来讲,Value就是指其属性值。X-DOM为XElement和XAttribute的Value属性提供了一致的操作方式。

设置Values

有两种方式来设置一个value:调用SetValue方法或设置Value属性。SetValue更加灵活因为它不只接受string类型的参数,还可以接受其他类型数据:

            var e = new XElement("date", DateTime.Now);
e.SetValue(DateTime.Now.AddDays(1));
Console.WriteLine(e.Value); // 2011-12-05T23:20:40.296875+08:00

上面的代码不只是设置了元素的Value属性,而且还意味着手动把DateTime值转换为string值。这种转换不是简单的调用ToString完成的,而是使用XmlConvert来得到一个符合XML格式要求的结果。

当我们把一个值传给XElement或XAttribute的构造函数时,对于非string类型参数会自动进行同样的转换。这保证了DateTime值被正确格式化,另外,true会被表示成小写形式,double.NegativeInfinity被表示成“-INF”。

获取Values

我们可以简单的把XElement或XAttribute强制转换为期望的数据类型来获得它的初始值,比如:

            XElement e = new XElement("now", DateTime.Now);
DateTime dt = (DateTime)e;
XAttribute a = new XAttribute("resolution", 1.234);
double res = (double)a;

一个元素或属性并不会在内部存放 DateTime或double值,而总是转换为字符串存放起来。他们也没有任何办法记起原来的类型,所以我们必须负责把他们转换为正确的类型,否则会出现运行时错误。为了让代码更加健壮,可以在try/catch代码块中进行数据转换并捕捉FormatException异常。

可以将XElement和XAttribute强制转换为如下数据类型:

  • 所有标准数值类型
  • string, bool, DateTime, DateTimeOffset, TimeSpan, Guid
  • 上述所列值类型的可空版本(Nullable<> versions)

转换为可空类型在与Element和Attribute方法一起使用时非常有效,因为即使请求的元素/属性不存在,转换也能正常完成,比如:

            // x 下面没有timeout元素
XElement x = new XElement("now", DateTime.Now);

// 下面的代码会产生运行时错误
int timeout = (int) x.Element ("timeout");

// OK; timeout2 is null.
int? timeout2 = (int?) x.Element ("timeout");

我们可以使用??操作符来去除最终结果中的可空类型。如下所示:

            // 如果resolution属性不存在,则使用默认值1.0
double resolution = (double?) x.Attribute ("resolution") ?? 1.0;

但是,如果元素或属性存在,但是拥有一个空值,或格式不正确的值,那么即使使用可空类型,我们还是会遇到麻烦。针对这种情况,我们必须捕捉FormatException异常。

我们也可以在LINQ查询中进行转换,下面的查询返回”John”:

            var data = XElement.Parse(
@"<data>
<customer id='1' name='Mary' credit='100' />
<customer id='2' name='John' credit='150' />
<customer id='3' name='Anne' />
</data>
");
// 转换为nullable int会防止Anne中出现空引用异常,因为他没有credit属性
IEnumerable<string> query = from cust in data.Elements()
where (int?)cust.Attribute("credit") > 100
select cust.Attribute("name").Value;

另一种解决方案是在where子句中添加一个条件:

            where cust.Attributes ("credit").Any() && (int) cust.Attribute...

Values和多种类型子节点

前面说到,我们可以通过Value属性来处理元素的XText子节点。那么你也许想知道,我们还需要直接处理XText节点吗?答案是当我们有多种类型的子节点时。比如:

<summary>An XAttribute is <bold>not</bold> an XNode</summary>

一个简单的Value属性并不能完全表示summary的内容。Summary元素包含了三个子节点:XText node、XElement、另一个XText node。下面是构建该summary的代码:

            XElement summary = new XElement("summary",
new XText("An XAttribute is "),
new XElement("bold", "not"),
new XText(" an XNode")
);

有意思的是,我们还是可以查询summary的Value属性,它并不会抛出异常。但是,它会返回所有子节点的Value属性在经过连接之后形成的一个字符串值:An XAttribute is not an XNode

当然,我们也可以重新对summary的Value属性赋值,只是它会替换上面所有的子节点。

XText自动拼接

当我们在XElement中添加简单的字符串值时,X-DOM会把值拼接在已有XText子节点的后面,而不是创建新的XText子节点。下面的示例中,e1和e2都只有一个XText节点,其Value为HelloWorld:

            var e1 = new XElement("test", "Hello"); e1.Add("World");
var e2 = new XElement("test", "Hello", "World");
Console.WriteLine(e1.Nodes().Count()); // 1
Console.WriteLine(e2.Nodes().Count()); // 1

但如果我们明确指定创建XText节点,则我们会得到多个子节点:

            var e = new XElement("test", new XText("Hello"), new XText("World"));
Console.WriteLine(e.Value); // HelloWorld
Console.WriteLine(e.Nodes().Count()); // 2

下一篇博客中我会和大家讨论LINQ to XML中的Documents、Declarations和Namespaces。


系列博客导航:

LINQ之路系列博客导航

LINQ之路 1:LINQ介绍

LINQ之路 2:C# 3.0的语言功能(上)

LINQ之路 3:C# 3.0的语言功能(下)

LINQ之路 4:LINQ方法语法

LINQ之路 5:LINQ查询表达式

LINQ之路 6:延迟执行(Deferred Execution)

LINQ之路 7:子查询、创建策略和数据转换

LINQ之路 8:解释查询(Interpreted Queries)

LINQ之路 9:LINQ to SQL 和 Entity Framework(上)

LINQ之路10:LINQ to SQL 和 Entity Framework(下)

LINQ之路11:LINQ Operators之过滤(Filtering)

LINQ之路12:LINQ Operators之数据转换(Projecting)

LINQ之路13:LINQ Operators之连接(Joining)

LINQ之路14:LINQ Operators之排序和分组(Ordering and Grouping)

LINQ之路15:LINQ Operators之元素运算符、集合方法、量词方法

LINQ之路16:LINQ Operators之集合运算符、Zip操作符、转换方法、生成器方法

LINQ之路17:LINQ to XML之X-DOM介绍

LINQ之路18:LINQ to XML之导航和查询

LINQ之路19:LINQ to XML之X-DOM更新、和Value属性交互

LINQ之路20:LINQ to XML之Documents、Declarations和Namespaces

LINQ之路21:LINQ to XML之生成X-DOM(Projecting)

LINQ之路系列博客后记

转载于:https://www.cnblogs.com/lifepoem/archive/2011/12/09/2281577.html

相关文章:

明朝是中国历史上最有骨气的王朝?【ZZ】

linked from http://www.guoxue.com/article/list.asp?id6095明朝是中国历史上最有骨气的王朝&#xff1f;作者&#xff1a; &#xff08;国学网2006-5-12发布&#xff09; 有人对明朝极尽污蔑之能事&#xff0c;好象明朝是最不中用的朝代。其实&#xff0c;只要细心比较&am…

马哥第七次作业

系统的INPUT和OUTPUT默认策略为DROP&#xff0c;请完成以下关于iptables的题目&#xff1b;1、限制本地主机的web服务器在周一不允许访问&#xff1b;新请求的速率不能超过100个每秒&#xff1b;web服务器包含了admin字符串的页面不允许访问&#xff1b;web服务器仅允许响应报文…

Strategy_Pattern

以下代码是“策略模式”的第四个例子&#xff1a;

JAVA-基础(Class对象及反射)

JAVA-基础&#xff08;Class对象及反射&#xff09; 1.&#xff08;1&#xff09;什么是class对象&#xff1f; 首先&#xff0c;java有两种对象&#xff0c;第一种是实例对象&#xff0c;第二种是Class对象&#xff0c;每一个类运行的类型信息就是用Class对象表示的&#xff0…

当年学生的一件事,心情很难过

当年学生的一件事&#xff0c;心情很难过 今天同一个以前的学生聊天&#xff0c;搞得心情很难过。那年是刚毕业&#xff0c;带了几个学生的毕业论文&#xff0c;其中有一个&#xff0c;只是第一次见过一面&#xff0c;最后答辩前见一两天以及答谢见过一面。他从来不同我联系&am…

while循环中,break,continue,return的差别

break 结束循环&#xff0c;跳出循环体&#xff1b;continue 结束本次循环。进行下次循环&#xff1b;return 跳出循环体所在的方法&#xff0c;相当于跳出循环体。

Strategy_Level2

以下代码是“策略模式”的第五个例子&#xff1a;

自制绘图之坐标轴

写代码之前得先了解坐标轴的一些属性&#xff0c;坐标轴有范围&#xff0c;每隔多少显示一条数值信息。然而间隔信息有时并不确定&#xff0c;一旦设置不准确&#xff0c;图形会乱掉。最好的方法是使用另一个参数&#xff1a;分隔符总数。这样可以利用坐标范围计算出间隔。 首先…

DotNET(C#) Socket基本编程 (1)

Socket基本编程 服务端&#xff1a; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; Thread mythread ; Socket socket; // 清理所有正在使用的资源。 protected override void Dispose( bool disposing ) { try {    socket.Clos…

CC2540 OSAL 学习其中原理,以及 给任务 添加 一个事件(定时发送串口消息)

参考学习大神博客&#xff1a; http://blog.csdn.net/feilusia/article/details/51083953 &#xff1a; http://blog.csdn.net/xiaoleiacmer/article/details/41723583 1、TI 的 CC2540跑了一个 OSAL (Operating System Abstraction Layer) 心得&#xff1a;大概 就是 一个循…

Strategy_Level3

以下代码是“策略模式”的第六个例子&#xff1a;

SDK开发日积月累(二)

WM_NOTIFY消息和WM_COMMAND消息在一个对话框中&#xff0c;子控件可以有两种方式与父对话框通信。1.向父对话框发送WM_COMMAND消息&#xff0c;但这种消息传递的信息量比较少。2.向父对话框发送WM_NOTIFY消息&#xff0c;信息量比较大。idCtrl (int) wParam; pnmh (LPNMHDR) …

关于IP地址的分类

我们说过因特网是把全世界的无数个网络连接起来的一个庞大的网间网&#xff0c;每个网络中的计算机通过其自身的IP地址而被唯一标识的&#xff0c;据此我们也可以设想&#xff0c;在INTERNET上这个庞大的网间网中&#xff0c;每个网络也有自己的标识符。这与我们日常生活中的电…

Visual Studio UML Activity Diagram(1)

数理系LSGO软件技术团队能够存活下来&#xff0c;并形成战斗力的根本原因&#xff0c;归结为我们的价值观。我们“只问收获&#xff0c;不问耕耘”&#xff0c;对知识是贪婪的&#xff0c;我们会把所学的知识放到场景中去应用&#xff0c;我们一定要做出成品。我们强调“要构建…

VMware 克隆Linux后找不到eth0

VMware 克隆Linux,ifconfig 不出现eth0解决方案:1)删除 /etc/udev/rules.d/70-persistent-net.rules/rm -rf /etc/udev/rules.d/70-persistent-net.rules2)重启init 6 3)ifconfig 查看转载于:https://blog.51cto.com/ictedu/1917185

笔试算法题(58):二分查找树性能分析(Binary Search Tree Performance Analysis)

议题&#xff1a;二分查找树性能分析&#xff08;Binary Search Tree Performance Analysis&#xff09; 分析&#xff1a; 二叉搜索树&#xff08;Binary Search Tree&#xff0c;BST&#xff09;是一颗典型的二叉树&#xff0c;同时任何节点的键值大于等于该节点左子树中的所…

定义自定义的异常

首先我们建立自己的异常类CustomException&#xff0c;它要继承自ApplicationException类&#xff08;这是一个在发生非致命的应用程序错误时抛出的通用异常&#xff0c;它又继承于更为通用的Exception类&#xff09;&#xff0c;将其用作为应用程序定义的任何自定义异常的基类…

python3 的 round 函数的 练习

python3 的 round 函数感觉很别扭&#xff0c;其运算结果与习惯不相符。特记录下来&#xff1a; 代码 python 3的 round 函数 是“四舍六入五成双”的https://www.zhihu.com/question/20128906print(python 3的 round 函数&#xff1a;四舍六入五成双)print(\nround(-3.5) , …

Visual Studio UML Activity Diagram(2)

昨天的图文介绍了Visual Studio UML Activity Diagram中所涉及的对象&#xff0c;今天图文我们来介绍这些对象的属性部分并给出UML关于Activity Diagram的元模型类图。通常情况下&#xff0c;我们在做一套软件系统的时候&#xff0c;对甲方业务流程并不熟悉&#xff0c;如果直接…

Go 语言中手动内存管理

2019独角兽企业重金招聘Python工程师标准>>> Go 语言是自带GC的, 相对C语言等的手动内存管理省事很多, 弊端便是会消耗更多的内存, 以及在GC时导致整个程序的停顿. 在某些特殊场合, 如果能够可选地手动进行内存管理, 效果会好不少. Go 目前的 GC 实现比较简单(mark-…

依赖倒转原则(Dependency Inversion Principle,DIP)

前面两篇图文介绍了“开闭原则”和“里氏替换原则”。开发出对扩展开放&#xff0c;对修改封闭的系统是程序员的目标&#xff0c;而今天所介绍的“依赖倒转原则”正是实现这一目标的途径之一&#xff0c;而“里氏替换原则”为这一途径提供了保证。大家或许发现&#xff0c;我写…

细说浏览器特性检测(2)-通用事件检测

在上一篇中介绍了jQuery1.4版本新增的几个浏览器特性检测方案和具体的目的&#xff0c;本文将以事件为中心&#xff0c;介绍一个较为完整、通用的事件检测方案。 事件检测&#xff0c;即检测某一事件在不同的浏览器中是否存在&#xff08;可用&#xff09;&#xff0c;这在编写…

robot简单功能测试脚本设计(例子)

以学生管理系统的添加一个学生信息为例子页面对象&#xff1a;editbox&#xff08;姓名&#xff09;,button&#xff08;添加&#xff09;数据要求&#xff1a;1 姓名不能为空2 姓名不能重复程序结构1 点button&#xff0c;弹出对话框“姓名不能为空”2 输入姓名&#xff0c;点…

里氏替换原则(Liskov Substitution Principle,LSP)

昨天图文介绍了软件设计的一个基本原则“开闭原则”&#xff0c;而“开闭原则”的核心就是通过抽象把需求变化进行隔离&#xff0c;这种想法可以通过“里氏替换原则”进行保证。理解“里氏替换原则”也是理解面向对象中“运行时多态”的关键。希望大家仔细体会。

在IIS7里配置 ISAPI,运行dll程序,总提示下载dll

在IIS7里配置 ISAPI&#xff0c;运行dll程序&#xff0c;总提示下载dll&#xff0c;只需要把对应站点应用程序池里面的高级设置里的启用32位应用程序&#xff0c;设为“true"即可。

MySQL数据库高可用集群搭建-PXC集群部署

Percona XtraDB Cluster&#xff08;下文简称PXC集群&#xff09;提供了MySQL高可用的一种实现方法。集群是有节点组成的&#xff0c;推荐配置至少3个节点&#xff0c;但是也可以运行在2个节点上。 PXC原理描述&#xff1a; 分布式系统的CAP理论&#xff1a; C&#xff1a;一致…

搭建Jupyter学习环境

python notebook是一个基于浏览器的python数据分析工具&#xff0c;使用起来非常方便&#xff0c;具有极强的交互方式和富文本的展示效果。jupyter是它的升级版&#xff0c;它的安装也非常方便&#xff0c;一般Anaconda安装包中会自带。安装好以后直接输入jupyter notebook便可…

[转贴]2006十大经典语句

1. 骑白马的不一定是王子&#xff0c;他可能是唐僧&#xff1b; 2. 带翅膀的也不一定是天使&#xff0c;他可能是鸟人。 3. 站的更高&#xff0c;尿的更远。 4. 穿别人的鞋&#xff0c;走自己的路&#xff0c;让他们找去吧&#xff0c; 5. 我不是随便的人。我随便起来不是人 6.…

开放-封闭原则(The Open-Closed Principle,OCP)

自己设计的软件系统“易于维护”、“扩展性好”、“可重用”、“具有灵活性”&#xff0c;这是每位程序员所追求的目标。“开闭原则”为我们指明了方向&#xff0c;即我们所设计的软件尽量满足“开闭原则–对扩展开放&#xff0c;对修改关闭”&#xff0c;这样就能降低需求不断…

Interesting visualization tools for profiling.

Interesting visualization tools for profiling. http://dtrace.org/blogs/brendan/2012/03/17/linux-kernel-performance-flame-graphs/ http://dtrace.org/blogs/brendan/2013/07/01/detecting-outliers/转载于:https://www.cnblogs.com/kungfupanda/p/3245651.html