LINQ学习之旅——最后一站LTX之XML基本操作(下)
上一节,讲解了LINQ TO XML基本操作中的创建,今天继续讲解LINQ TO XML操作的下半部分:输入输出、遍历、查询及修改。
1.在LINQ TO XML中的输出和输出操作主要由Save和Load两个方法来完成的。其中XDocumnet和XElement类提供了Save方法来把xml数据输出到指定文件、TextWriter对象以及XmlWriter对象中,下面是XElement类中常用的几个Save方法原型:
public void Save(string fileName);
public void Save(TextWriter textWriter);
public void Save(XmlWriter writer);
public void Save(string fileName, SaveOptions options);
public void Save(TextWriter textWriter, SaveOptions options);
第一个方法原型就不再多说了,前几节在编写创建xml文档的示例中多次用到。第二个原型方法的参数是一个TextWriter对象,类TextWriter用来编写一个有序字符系列的编辑器。也是StreamWriter和StringWriter的抽象基类,将字符分别写入流和字符串;第三个方法原型的参数为一个XmlWriter对象,该类提供了只进、只读、不缓存的xml流生成方法。最后两种方法比起前三种就是多了一个类型为SaveOptions的参数,它用于设置xml输出的格式,是一个枚举类型,包含None、DisableFormatting和OmitDuplicateNamespaces枚举值,None表示序列化时对 XML 进行格式设置(缩进);DisableFormatting表示序列化时保留所有无关紧要的空白;OmitDuplicateNamespaces表示序列化时移除重复的命名空间声明。下面用示例来进一步说明Save使用:
i.xml输出:
1 static void Main(string[] args) 2 { 3 XElement Sprites = new XElement("Sprites", 4 new XElement("Sprite", 5 new XElement("Profession", "法师"), 6 new XElement("Weapon", "魔杖")), 7 new XElement("Sprite", 8 new XAttribute("Profession", "战士"), 9 new XAttribute("Weapon", "屠龙刀")),10 new XElement("Sprite",11 new XElement("Profession","道士"),12 new XElement("Weapon", "倚天剑")));13 14 //保存到指定文件15 Sprites.Save(@"d:\\Sprites.xml");16 17 //保存到TextWriter18 StringWriter sw = new StringWriter();19 Sprites.Save(sw,SaveOptions.DisableFormatting);20 Console.WriteLine(sw);21 22 //保存到XmlWriter23 XmlWriter xw = XmlWriter.Create(@"d:\\Sprites1.xml");24 Sprites.Save(xw);25 //写入文件26 xw.Flush();27 28 Console.Read();29 }
ii.结果:
①Sprites.xml文档:
②运行结果:
③Sprites1.xml文档:
输出xml数据用Save方法,那么输入就用Load方法,同样XDocumnet和XElement类提供了Load方法从xml文件、TextReader对象以及XmlReader对象将xml数据输入,另外还提供了Parse方法从字符串中提取xml数据。下面是XElement类中常用的几个Load方法:
public static XElement Load(string uri);
public static XElement Load(TextReader textReader);
public static XElement Load(XmlReader reader);
public static XElement Load(string uri, LoadOptions options);
public static XElement Load(TextReader textReader, LoadOptions options);
public static XElement Load(XmlReader reader, LoadOptions options);
从中可以看出Load方法和Save方法非常类似。这里就不再一一介绍,主要讲解一下其中涉及到的参数类型LoadOptions,它和SaveOptions一样也是一个枚举类型,用于输入时指定需要的处理,包含None、PreserveWhitespace、SetBaseUri和SetLineInfo四个枚举值。其中None不保留无关紧要的空白,也不加载基 URI 和行信息;PreserveWhitespace表示分析时保留无关紧要的空白;SetBaseUri表示在输入xml数据时加载基本URL信息,基URL信息可以通过XElement类的基类XObject的属性BaseUri读取;SetLineInfo表示输入xml数据时加载的行信息;下面通过实例来进一步说明Load方法的使用:
i.输入xml:
1 static void Main(string[] args) 2 { 3 XElement loadSprites = XElement.Load(@"d:\\Sprites.xml",LoadOptions.SetBaseUri|LoadOptions.SetLineInfo); 4 5 //添加新元素 6 loadSprites.Elements("Sprite").Last().AddAfterSelf( 7 new XElement("Sprite", 8 new XAttribute("Profession","猎人"), 9 new XAttribute("Weapon","弓箭")10 ));11 12 //输出xml信息13 Console.WriteLine(loadSprites);14 15 Console.WriteLine("---------------------------------");16 17 //获取文件基URL信息18 string baseUri = loadSprites.BaseUri;19 Console.WriteLine("xml基URL信息:{0}",baseUri);20 21 Console.WriteLine("---------------------------------");22 23 //输出xml中每一个元素的行信息24 foreach (var s in loadSprites.DescendantsAndSelf())25 {26 Console.WriteLine("元素名称:{0} 行信息:{1}",s.Name,27 ((IXmlLineInfo)s).HasLineInfo()?((IXmlLineInfo)s).LineNumber.ToString():"无行号");28 }29 30 Console.Read();31 }
ii.结果:
从运行结果中可以看出新添加的Sprite元素没有行信息。
除了用Load方法,XElement类中还有Parse方法用于将一段字符串中提取XML数据,其方法原型有两个:
public static XElement Parse(string text);
public static XElement Parse(string text, LoadOptions options);
下面用示例来说明Parse方法的使用:
i.Parse方法:
1 static void Main(string[] args) 2 { 3 //xml字符串 4 string str_xml = @"<Sprites> 5 <Sprite> 6 <Profession>法师</Profession> 7 <Weapon>魔杖</Weapon> 8 </Sprite> 9 <Sprite>10 <Profession>战士</Profession>11 <Weapon>屠龙刀</Weapon>12 </Sprite>13 <Sprite>14 <Profession>道士</Profession>15 <Weapon>倚天剑</Weapon>16 </Sprite>17 </Sprites>";18 19 XElement SpritesFromString = XElement.Parse(str_xml);20 Console.WriteLine(SpritesFromString);21 22 Console.Read();23 }
ii.结果:
2.除了xml的输入输出操作会经常用到外,对xml数据的遍历操作使用也是很频繁。在LINQ TO XML编程接口类中,主要通过属性和方法来遍历xml,其中最常用的遍历属性有:XNode类的NextNode属性和PreviousNode属性,XObject类的Document属性和Parent属性。NextNode属性用于返回当前节点的下一个节点,PreviousNode属性则返回当前节点上一个节点,Document属性返回当前节点的文档对象,Parent属性返回当前节点的父节点信息。下面通过示例来验证这四个属性的作用:
i.遍历属性:
1 static void Main(string[] args) 2 { 3 //建立xml文档 4 XDocument document = new XDocument(); 5 6 //建立节点 7 XNode node; 8 XElement SpritesForeach = new XElement("Sprites", 9 new XElement("Sprite",10 new XElement("Profession", "法师"),11 new XElement("Weapon", "魔杖")),12 13 new XElement("Sprite",14 node=new XElement("Profession", "战士"),15 new XElement("Weapon", "屠龙刀")),16 17 new XElement("Sprite",18 new XElement("Profession", "道士"),19 new XElement("Weapon", "倚天剑")));20 21 //添加根元素到文档对象中22 document.Add(SpritesForeach);23 24 //当前节点上一个节点25 Console.WriteLine("当前节点上一个节点:{0}",node.PreviousNode);26 27 //当前节点28 Console.WriteLine("当前节点:{0}",node);29 30 //当前节点的下一个节点31 Console.WriteLine("当前节点的下一个节点:{0}",node.NextNode);32 33 //当前节点的文档对象34 Console.WriteLine("当前节点的文档对象:{0}",node.Document);35 36 //当前节点的父节点37 Console.WriteLine("当前节点的父节点:{0}",node.Parent);38 39 Console.Read();40 }
ii.结果:
下面介绍XML中常用的遍历方法:XContainer类中的Nodes方法、Elements方法、Element方法和Descendants方法,XNode类中的Ancestors方法、NodesAfterSelf方法、NodesBeforeSelf方法、ElementsAfterSelf方法以及ElementsBeforeSelf方法,XElement类中的AncestorsAndSelf方法和DescendantsAndSelf方法。其中XContainer类中的Elements方法和Nodes方法相似,都是用于返回当前节点的子节点集合,只不过Elements方法返回的序列元素类型为XElement,而Nodes返回的集合元素类型是XNode,方法Element返回当前节点的下级元素中具有指定名称的第一个元素,而方法Descendants返回的是当前节点的直接子元素节点,还包括子元素节点的后代子元素节点。下面通过示例来具体说明XContainer类的遍历方法:
i.XContainer类的遍历方法:
1 static void Main(string[] args) 2 { 3 //建立节点 4 XNode node; 5 //建立元素 6 XElement element; 7 //建立xml数据源 8 XElement SpritesForeach = new XElement("Sprites", 9 new XElement("Sprite",10 new XElement("Profession", "法师"),11 new XElement("Weapon", "魔杖")),12 13 new XElement("Sprite",14 node=new XElement("Profession", "战士"),15 new XElement("Weapon", "屠龙刀")),16 17 new XElement("Sprite",18 new XElement("Profession", "道士"),19 element = new XElement("Weapon", "倚天剑")));20 21 //当前节点的下一级元素中第一个名为Sprite的元素22 XElement CurrentElement = SpritesForeach.Element("Sprite");23 Console.WriteLine("当前节点的下一级元素中第一个名为Sprite的元素:\n{0}",CurrentElement);24 25 //当前节点所有下级节点26 Console.WriteLine("当前节点所有下级节点:");27 foreach (var n in CurrentElement.Nodes())28 {29 Console.WriteLine(n);30 }31 32 //当前节点所有的后代节点33 Console.WriteLine("当前节点所有的后代节点:");34 foreach (var n in CurrentElement.Descendants())35 {36 Console.WriteLine("元素名:{0}",n.Name);37 Console.WriteLine(n);38 Console.WriteLine("--------------------------------");39 }40 41 Console.Read();42 }
ii.结果:
XNode类的方法Ancestors用于返回当前节点的所有祖先节点,NodesAfterSelf方法和NodesBeforeSelf方法用于返回当前节点所有后续节点和所有前驱节点。ElementsAfterSelf方法与ElementsBeforeSelf方法和NodesAfterSelf方法和NodesBeforeSelf方法类似,只不过返回的结合元素类型不同。下面通过示例具体说明XNode类的遍历方法:
i.XNode类的遍历方法:
1 static void Main(string[] args) 2 { 3 //建立节点 4 XNode node; 5 //建立元素 6 XElement element; 7 //建立xml数据源 8 XElement SpritesForeach = new XElement("Sprites", 9 new XElement("Sprite",10 new XElement("Profession", "法师"),11 new XElement("Weapon", "魔杖")),12 13 new XElement("Sprite",14 node=new XElement("Profession", "战士"),15 new XElement("Weapon", "屠龙刀")),16 17 new XElement("Sprite",18 new XElement("Profession", "道士"),19 element = new XElement("Weapon", "倚天剑")));20 21 //当前节点的所有祖先元素22 Console.WriteLine("当前节点的所有祖先元素:");23 foreach (var e in node.Ancestors())24 {25 Console.WriteLine("元素名:{0}", e.Name);26 Console.WriteLine(e);27 Console.WriteLine("---------------------------------");28 }29 30 //当前节点的所有后续节点31 Console.WriteLine("当前节点的所有后续节点:");32 foreach (var n in node.NodesAfterSelf())33 {34 Console.WriteLine(n);35 }36 37 //当前节点的所有前驱节点38 Console.WriteLine("当前节点的所有前驱节点:");39 foreach (var n in node.NodesBeforeSelf())40 {41 Console.WriteLine(n);42 }43 44 Console.Read();45 }
ii.结果:
XElement类的AncestorsAndSelf方法和DescendantsAndSelf方法,分别用于返回当前元素和当前元素的所有祖先元素和返回当前元素和当前元素的所有后代元素。下面通过示例具体说明XElement类的遍历方法:
i.XElement类的遍历方法:
1 static void Main(string[] args) 2 { 3 //建立节点 4 XNode node; 5 //建立元素 6 XElement element; 7 //建立xml数据源 8 XElement SpritesForeach = new XElement("Sprites", 9 new XElement("Sprite",10 new XElement("Profession", "法师"),11 new XElement("Weapon", "魔杖")),12 13 new XElement("Sprite",14 node=new XElement("Profession", "战士"),15 new XElement("Weapon", "屠龙刀")),16 17 new XElement("Sprite",18 new XElement("Profession", "道士"),19 element = new XElement("Weapon", "倚天剑")));20 21 //当前元素和其所有的祖先元素22 Console.WriteLine("当前元素和其所有的祖先元素:");23 foreach (var e in element.AncestorsAndSelf())24 {25 Console.WriteLine("元素名:{0}",e.Name);26 Console.WriteLine(e);27 Console.WriteLine("----------------------------------");28 }29 30 //当前元素和其所有的后代元素31 Console.WriteLine("当前元素和其所有的后代元素:");32 foreach (var e in element.DescendantsAndSelf())33 {34 Console.WriteLine("元素名:{0}", e.Name);35 Console.WriteLine(e);36 Console.WriteLine("----------------------------------");37 }38 39 Console.Read();40 }
ii.结果:
3.同样的,在LINQ TO XML中也提供了许多方法和属性来修改XML节点的内容,其中属性中最常用的就是很多LINQ TO XML编程接口类中都有的Value属性,通过它来修改XML节点或元素中的值。而方法就更多了,包括添加节点、修改节点和删除节点等操作。XContainer类中的添加节点方法有Add和AddFirst方法,删除节点的方法有RemoveNodes,其中Add方法用于添加为当前节点的子节点,如果当前节点已经包含子节点,则将新的节点追加为最后一个子节点。而AddFirst方法则是将指定的节点添加为当前节点的第一个子节点。RemoveNodes方法用于将当前节点下的子节点删除。下面通过示例来具体说明XContainer类中修改xml的方法:
i.XContainer类的xml修改方法:
1 static void Main(string[] args) 2 { 3 //建立节点 4 XNode node; 5 6 //建立元素 7 XElement element; 8 9 //建立xml数据源10 XElement Sprites = new XElement("Sprites",11 new XElement("Sprite01",12 new XElement("Profession", "法师"),13 new XElement("Weapon", "魔杖")),14 new XElement("Sprite",15 new XElement("Profession", "战士"),16 node = new XElement("Weapon", "屠龙刀")),17 element= new XElement("Sprite",18 new XAttribute("Profession", "道士"),19 new XAttribute("Weapon", "倚天剑")));20 21 22 //添加为最后一个子节点23 Sprites.Add(new XElement("Sprite",24 new XAttribute("Profession", "猎人"),25 new XAttribute("Weapon", "弓箭")26 ));27 28 //添加为第一个子节点29 Sprites.AddFirst(new XElement("Sprite",30 new XAttribute("Profession", "骑士"),31 new XAttribute("Weapon", "方天画戟")32 ));33 34 //删除子节点35 Sprites.Element("Sprite01").RemoveNodes();36 37 Console.WriteLine(Sprites);38 39 Console.Read();40 }
ii.结果:
除了类XContainer中的方法可以修改节点外,还有就是XNode类中的AddAfterSelf方法和AddBeforeSelf方法,前者将指定内容添加为自身节点的前一个节点,后者则将指定内容添加为自身节点的后一个节点。删除自身节点则是用XNode类中的Remove方法。下面通过示例来具体说明XNode类中修改xml的方法:
i.XNode类的xml修改方法:
1 static void Main(string[] args) 2 { 3 //建立节点 4 XNode node; 5 6 //建立元素 7 XElement element; 8 9 //建立xml数据源10 XElement Sprites = new XElement("Sprites",11 new XElement("Sprite01",12 new XElement("Profession", "法师"),13 new XElement("Weapon", "魔杖")),14 new XElement("Sprite",15 new XElement("Profession", "战士"),16 node = new XElement("Weapon", "屠龙刀")),17 element= new XElement("Sprite",18 new XAttribute("Profession", "道士"),19 new XAttribute("Weapon", "倚天剑")));20 21 //添加为自身节点的前一个节点22 node.AddBeforeSelf(new XElement("Weapon", "雪饮刀"));23 24 //添加为自身节点的后一个节点25 node.AddAfterSelf(new XElement("Weapon", "狼牙棒"));26 27 //删除自身节点28 Sprites.FirstNode.Remove();29 30 Console.WriteLine(Sprites);31 32 Console.Read();33 }
ii.结果:
还有就是用XElement类方法来修改xml中的元素内容,同时它也提供了Attribute方法来辅助Value属性对xml属性内容进行修改,或直接用SetAttributeValue来代替,SetElementValue方法用于修改指定元素的值。而删除自身所有子节点和属性则用RemoveAll方法,删除元素属性用RemoveAttributes方法。下面通过示例来具体说明XElement类中修改xml的属性和方法:
i.XElement类的xml修改属性和方法:
1 static void Main(string[] args) 2 { 3 //建立节点 4 XNode node; 5 6 //建立元素 7 XElement element; 8 9 //建立xml数据源10 XElement Sprites = new XElement("Sprites",11 new XElement("Sprite01",12 new XElement("Profession", "法师"),13 new XElement("Weapon", "魔杖")),14 new XElement("Sprite",15 new XElement("Profession", "战士"),16 node = new XElement("Weapon", "屠龙刀")),17 element= new XElement("Sprite",18 new XAttribute("Profession", "道士"),19 new XAttribute("Weapon", "倚天剑")));20 21 //Name属性修改22 Sprites.Element("Sprite01").Name="Sprite";23 24 //Value属性修改25 element.Attribute("Weapon").Value="火麟剑";26 //或27 //element.SetAttributeValue("Weapon", "火麟剑");28 29 //删除元素属性30 element.RemoveAttributes();31 32 //或33 //删除自身所有子节点和属性34 //element.RemoveAll();35 36 Console.WriteLine(Sprites);37 38 Console.Read();39 }
ii.结果:
最后来说说LINQ TO XML中查询,看到查询你就应该会回忆起之前在LINQ TO Object系列当中所讲的标准查询操作符,其实这些查询符在LINQ TO XML中也依然受用,只不过操作的序列元素的类型可能会是XElement或XNode等等。那么在这里就简单地用一个示例来说明一下LINQ TO XML中的查询操作:
i.xml源文件:
1 <?xml version="1.0" encoding="utf-8" ?> 2 <Sprites> 3 <Sprite> 4 <Profession>法师</Profession> 5 <Weapon>魔杖</Weapon> 6 </Sprite> 7 <Sprite> 8 <Profession>战士</Profession> 9 <Weapon>屠龙刀</Weapon>"10 </Sprite>11 <Sprite>12 <Profession>道士</Profession>13 <Weapon>倚天剑</Weapon>14 </Sprite>15 </Sprites>
ii.XML查询操作:
1 static void Main(string[] args) 2 { 3 //读取xml文件 4 XElement xml = XElement.Load("Sprites.xml"); 5 6 //查询所有元素名为Sprite的元素 7 var sprites = from s in xml.Descendants("Sprite") 8 select new { 9 Profession = s.Element("Profession").Value,10 Weapon=s.Element("Weapon").Value11 };12 13 //输出sprites信息14 foreach (var s in sprites)15 {16 Console.WriteLine("精灵职业:{0}",s.Profession);17 Console.WriteLine("主要武器:{0}",s.Weapon);18 Console.WriteLine("----------------------------------------");19 }20 21 Console.Read();22 }
iii.结果:
转载于:https://www.cnblogs.com/CaiNiaoZJ/archive/2011/09/25/2188400.html
LINQ学习之旅——最后一站LTX之XML基本操作(下)相关推荐
- LINQ学习之旅——最后一站LTX之基础和编程接口所包含类的简介
对LINQ TO SQL的内容讲解将告一段落,下面我们进入LINQ学习之旅的最后一站"LTX",即LINQ TO XML.当前XML技术在应用开发中显得越来越重要,已成为各类数据交 ...
- LINQ学习之旅——再次拾起
记得最早接触到LINQ技术是在风云的银光志silverlight3.0开发详解与最佳实践一书中.它也是我学习Silverlight技术最初的"导师".因为其中主要是讲到Linq t ...
- LINQ学习之旅——准备(2)
上一节,我有提到过LINQ中还大量使用了C#3.0的一些新的语言特性,比如:局部变量类型推断.Lambda表达式.表达式树以及扩展方法.这些特性就是我今天主要讲的内容,也是学习LINQ的第二项准备工作 ...
- LINQ学习之旅——准备(C#3.0新特性补充)
今天主要是对上一节所说的C#3.0的新特性做些补充:对象及集合初始化表达式.匿名类型.局部方法以及查询表达式.这些特性在LINQ中使用也很频繁,尤其是查询表达式. 1.对象初始化表达式允许开发者在一条 ...
- LINQ学习之旅——第二站LTQ之标准数据库操作(增查删改)
今天要讲解主要内容是关于LINQ TO SQL中的标准数据库操作:插入(Insert).查询(Select).更新(Update)以及删除(Delete),凡是涉及到数据库方面的都会使用这些操作.而这 ...
- LinQ学习之旅(1)
关注.NET的程序员,对LinQ这个名词应该已经听说过了,上个星期和THIN见了一下面,他给我演示了一下LinQ,觉得很有意思,有些东西很像JavaScript.后来在他的博客里也看到他写的一编文章. ...
- WCF学习之旅—基于Fault Contract 的异常处理(十八)
WCF学习之旅-WCF中传统的异常处理(十六) WCF学习之旅-基于ServiceDebug的异常处理(十七) 三.基于Fault Contract 的异常处理 第二个示例是通过定制Servic ...
- WCF学习之旅—实现支持REST客户端应用(二十四)
WCF学习之旅-实现REST服务(二十二) WCF学习之旅-实现支持REST服务端应用(二十三) 在上二篇文章中简单介绍了一下RestFul与WCF支持RestFul所提供的方法,及创建一个支持RES ...
- WCF学习之旅—第三个示例之四(三十)
上接WCF学习之旅-第三个示例之一(二十七) WCF学习之旅-第三个示例之二(二十八) WCF学习之旅-第三个示例之三(二十九) ...
最新文章
- Android用户界面开发(11):Menu
- Android studio ButterKnife插件
- java线程等待都完成_Java等待线程完成
- 【代码规范】常见排版规范
- layer和3D仿射变换
- java程序员_Java程序员工资为什么这么高?
- 流程控制介绍,顺序结构、分支结构、循环结构、Promise对象、throw语句、break和continue关键字
- java.lang.NoClassDefFoundError: Ljavax/transaction/TransactionManager
- 分布式服务-DUBBOX(五):集成服务生产者
- 深度残差网络_深度残差收缩网络:(三) 网络结构
- 蓝天采集系统的安装和遇到的问题及解决方案
- [转载] Python 多项式拟合(一元回归)
- python函数第二次运行报错_(数据科学学习手札54)Python中retry的简单用法
- jqprint 打印表格宽度_只要30秒!快速解决Excel表格打印问题
- 添加几行代码实现百度文库的复制
- 关于Python对于图像处理详解
- IDEA 启动tomcat 或者springboot 卡住问题
- ALG 求单峰的位置
- Python爬虫企查查
- 利用百度指数和热词排行榜提升网站流量
热门文章
- Zabbix使用Python监控阿里云ECS
- ABBYY FineReader如何识别多语言文档
- viewport 深入理解
- 谈谈中行E令可能存在的问题
- 【Java加解密系列】- SM2加解密
- 怎么把计算机磁盘解密,Win10系统下怎样对磁盘进行加密、解密?Win10系统加密、解密磁盘图文教程...
- 2019年ACM-ICPC - 南昌网络赛I:Yukino With Subinterval【带修主席树】
- 利用python中的zipfile模块进行解压缩
- 英文字母和中文汉字在不同字符集编码下的字节数(详细解释)
- mac mysql dmg安装_mac上面MYSQL安装