C#中的Linq?To?XML講解
一、概述
Overview - LINQ to XML | Microsoft 官方文檔
LINQ to XMLLINQ to XML 是一種啟用了 LINQ 的內(nèi)存 XML 編程接口,使用它,可以在 .NET Framework.NET Framework 編程語(yǔ)言中處理 XML。
在使用LINQ to XML時(shí)需要添加System.Xml.Linq.dll的引用。
- XElement類(lèi) 表示XML元素,它是XContainer類(lèi)的派生類(lèi),而XContainer類(lèi)又派生于XNode類(lèi)。一個(gè)元素就是一個(gè)節(jié)點(diǎn)。
XElement是LINQ to XML最重要最基本的類(lèi)之一,它包含所有創(chuàng)建和操作XML元素所必需的功能。通過(guò)它可以創(chuàng)建元素,添加和修改元素的屬性,操作元素的內(nèi)容等。 - XAttribute類(lèi) 用來(lái)處理屬性,屬性是與元素相關(guān)聯(lián)的名稱/值對(duì)。
- XDocument類(lèi) 提供了處理有效XML文檔的方法,包括聲明、注釋和處理指令。XDocument類(lèi)派生自XContainer類(lèi),可以有子節(jié)點(diǎn)。XML標(biāo)準(zhǔn)限值XDocument對(duì)象只包含單個(gè)XElement子節(jié)點(diǎn),此節(jié)點(diǎn)作為根節(jié)點(diǎn)或跟元素。
繼承關(guān)系:
XNode(抽象)類(lèi)派生類(lèi)有:XText、XComment、XDocumentType、XProcessingInstruction、XContainer
XContainer(抽象)類(lèi)派生類(lèi)有:XElement、XDocument.
二、加載XML文件
1、從文件中輸入XML數(shù)據(jù)
//1、從URI中獲取XML數(shù)據(jù),支持本地路徑和URL,支持對(duì)應(yīng)枚舉的設(shè)置 XElement xe1 = XElement.Load(@"D:\123.xml",LoadOptions.None); //2、從XmlReader中加載 XmlReader xr = XmlReader.Create(@"D:\123.xml"); XElement xe2 = XElement.Load(xr); //3、從TextReader中獲取數(shù)據(jù) TextReader reader = File.OpenText(@"D:\123.xml"); XElement xe3 = XElement.Load(reader); //4、從Stream中讀取 XElement xe4 = XElement.Load(new FileStream(@"D:\123.xml", FileMode.Open, FileAccess.Read));
2、從字符串中輸入XML數(shù)據(jù)
string xmlString = "劉備28"; XElement xe = XElement.Parse(xmlString, LoadOptions.SetLineInfo);
三、生成XML元素或XML文檔
1、創(chuàng)建XML元素
XElement xml = new XElement("Persons", new XElement("Person", new XElement("Name", "劉備"), new XElement("Age", "28") ), new XElement("Person", new XElement("Name", "關(guān)羽"), new XElement("Age", "27") ) ); xml.Save(@"D:\123.xml");
2、創(chuàng)建XML文檔
//創(chuàng)建處理指令 XProcessingInstruction instruction = new XProcessingInstruction("xml-stylesheet","href=\"hello.css\" type = \"text/css\""); //創(chuàng)建聲明對(duì)象 XDeclaration xDeclaration = new XDeclaration("1.0","GB2312","yes"); //創(chuàng)建文檔類(lèi)型 XDocumentType documentType = new XDocumentType("Person", null, "Person.dtd", null); //創(chuàng)建XmlCData數(shù)據(jù) XCData data = new XCData("神奇的劉備"); //創(chuàng)建XDocument文檔 XDocument xDoc = new XDocument(); XElement xml = new XElement("Persons", new XElement("Person", new XAttribute("Description", "此人龍鳳之姿 天日之表;"), new XElement("Name", data), new XElement("Age", "28") ), new XElement("Person", new XElement("Name", "關(guān)羽"), new XElement("Age", "27") ) ); xDoc.Add(documentType); xDoc.Add(instruction); xDoc.Declaration = xDeclaration; xDoc.Add(xml); xDoc.Save(@"D:\123.xml");
3、Linq查詢生成XML
我們實(shí)例化一個(gè)book的集合
Book[] books = new Book[] { new Book("Ajax in Action", "Manning", 2005), new Book("Windows Forms in Action", "Manning", 2006), new Book("RSS and Atom in Action", "Manning", 2006) };
如果我們現(xiàn)在想將Year== 2006的集合創(chuàng)建成以下XML格式
<books> <book title="Windows Forms in Action"> <publisher>Manning</publisher> </book> <book title="RSS and Atom in Action"> <publisher>Manning</publisher> </book> </books>
采用linq方式
XElement xml = new XElement("books", from book in books where book.Year == 2006 select new XElement("book", new XAttribute("title", book.Title), new XElement("publisher", book.Publisher) ) ); // 顯示這個(gè)XML Console.WriteLine(xml);
傳統(tǒng)方式
XmlDocument doc = new XmlDocument(); XmlElement root = doc.CreateElement("books"); foreach (Book book in books) { if (book.Year == 2006) { XmlElement element = doc.CreateElement("book"); element.SetAttribute("title", book.Title); XmlElement publisher = doc.CreateElement("publisher"); publisher.InnerText = book.Publisher; element.AppendChild(publisher); root.AppendChild(element); } } doc.AppendChild(root); // 顯示這個(gè)XML doc.Save(Console.Out);
4、屬性轉(zhuǎn)出元素
XML文件:
<?xml version="1.0" encoding="utf-8" ?> <Root Data1="123" Data2="456"> <Child1>Content</Child1> </Root>
您可以編寫(xiě)一些過(guò)程代碼以便從屬性創(chuàng)建元素,然后刪除屬性
linq方式:
XElement root = XElement.Load("Data.xml"); XElement newTree = new XElement("Root", root.Element("Child1"), from att in root.Attributes() select new XElement(att.Name, (string)att) ); xml.Save(@"D:\123.xml");
傳統(tǒng)方式:
XElement root = XElement.Load("Data.xml"); foreach (XAttribute att in root.Attributes()) { root.Add(new XElement(att.Name, (string)att)); } root.Attributes().Remove();
5、XmlDocument轉(zhuǎn)換為XDocument
XmlDocument doc = new XmlDocument(); doc.LoadXml(xmlStr); //xml字符串轉(zhuǎn)成xml文檔對(duì)象 XDocument xdoc = doc.ToXDocument(); //xmldocument轉(zhuǎn)成xdoccument 擴(kuò)展方法 var eventId = xdoc.Document.Root.Element("EventID"); //根節(jié)點(diǎn)下的eventid節(jié)點(diǎn) if (eventId != null) { MessageBox.Show(eventId.Value); //15 }
擴(kuò)展方法
public static class XmlDocumentExtensions { public static XDocument ToXDocument(this XmlDocument document) { return document.ToXDocument(LoadOptions.None); } public static XDocument ToXDocument(this XmlDocument document, LoadOptions options) { using (XmlNodeReader reader = new XmlNodeReader(document)) { return XDocument.Load(reader, options); } } }
四、XML數(shù)據(jù)的輸出
XElement有個(gè)Save,這個(gè)Save有多種重載,支持將XML數(shù)據(jù)輸入到各處(文件地址,流,TextWriter,XmlWriter)。
XElement xml = new XElement("Persons", new XElement("Person", new XElement("Name", "劉備"), new XElement("Age", "28") ) ); //1、輸出到文件 xml.Save(@"D:\123.xml"); //2、輸出到TextWriter TextWriter tw = new StringWriter(); //第二個(gè)參數(shù)SaveOptions枚舉支持設(shè)置格式,縮進(jìn),保留無(wú)關(guān)重要的空白,去除重復(fù)命名空間 xml.Save(tw, SaveOptions.None); Console.WriteLine(tw); //3、輸出到Stream using (MemoryStream mem = new MemoryStream()) { xml.Save(mem); Console.WriteLine(Encoding.UTF8.GetString(mem.ToArray())); } //4、輸出到XmlWriter XmlWriter xw = XmlWriter.Create(@"D:\LinqToXml.xml"); xml.Save(xw); xw.Flush();
五、查詢
- Element() :獲取當(dāng)前XML元素的第一個(gè)具有指定名稱的子元素
- Elements() :獲取當(dāng)前XML元素的所有子元素,或具有指定名稱的所有子元素,返回類(lèi)型為IEnumerable的可用LINQ進(jìn)行查詢的元素集合
- Attribute(): 獲取當(dāng)前XML元素的具有指定名稱的屬性
- Attributes(): 獲取當(dāng)前XML元素的所有屬性或者具有指定名稱的屬性, 返回類(lèi)型為IEnumerable的LINQ集合
1、查詢根元素
IEnumerable elements = from e in doc.Elements("Products") select e; foreach (XElement e in elements) { Console.WriteLine("{0}-{1}", e.Name, e.Value); }
2、查詢節(jié)點(diǎn)
var query = from p in doc.Element("Products").Elements("Product") where (int)p.Element("ProductID") == 1 orderby p.Attribute("ID").Value select p; query.ToList().ForEach(item => { Console.WriteLine("{0}-{1}-{2}", item.Element("ProductID").Value, item.Element("ProductName").Value, item.Element("UnitPrice").Value); });
3、查詢子孫節(jié)點(diǎn)
Descendants軸方法與Elements類(lèi)型相似,不過(guò)Elements只查找當(dāng)前元素下的直接子節(jié)點(diǎn),而Descendants則會(huì)遍歷當(dāng)前元素下任意層級(jí)的子元素。
var query = from b in root.Descendants("Book") select b; foreach (var item in query) { Console.WriteLine(item.Element("ProductName").Value); }
4、查詢屬性
var query = from p in xml.Nodes().OfType() where (int)p.Attribute("ID").Value == 1 select new { ID = p.Attribute("ID").Value, ProductID = p.Element("ProductID").Value, ProductName = p.Element("ProductName").Value };
5、查詢出來(lái)填充到List:
XElement root = XElement.Load(@"like.xml"); var query = from ele in root.Elements("book") select new { author = ele.Element("author").Value, price = ele.Element("price").Value }; String xml = null; foreach (var item in query) { xml = xml + item.ToString() + "\n ------- \n"; }
六、操作節(jié)點(diǎn)
1、增加節(jié)點(diǎn)
- Add(): 在 XContainer 的子內(nèi)容的末尾添加內(nèi)容。
- AddFirst(): 在 XContainer 的子內(nèi)容的開(kāi)頭添加內(nèi)容。
- AddAfterSelf(): 在 XNode 后面添加內(nèi)容。
- AddBeforeSelf() : 在 XNode 前面添加內(nèi)容。
XElement product = new XElement ( "Product", new XAttribute("ID", 2), new XElement("ProductName", "LINQ to Object"), new XElement("UnitPrice", 20m), new XElement("Remark", "") ); el.Add(product);
2、修改、替換節(jié)點(diǎn)
- SetAttributeValue(): 設(shè)置屬性的值。 如果該屬性不存在,則創(chuàng)建該屬性。 如果值設(shè)置為 null,則移除該屬性。
- SetElementValue(): 設(shè)置子元素的值。 如果該元素不存在,則創(chuàng)建該元素。 如果值設(shè)置為 null,則移除該元素。
- Value:用指定的文本替換元素的內(nèi)容(子節(jié)點(diǎn))。
- SetValue(): 設(shè)置元素的值。
- ReplaceAll (): 替換元素的所有內(nèi)容(子節(jié)點(diǎn)和屬性)。
- ReplaceAttributes(): 替換元素的屬性。
- ReplaceWith(): 用新內(nèi)容替換節(jié)點(diǎn)。
- ReplaceNodes(): 用新內(nèi)容替換子節(jié)點(diǎn)。
IEnumerable products = from e in el.Elements("Product") where e.Attribute("ID").Value == "1" select e; if (products.Count() > 0) { XElement product = products.First(); product.SetAttributeValue("ID", 3); product.ReplaceNodes ( new XElement("ProductName", "LINQ to XML Version 2"), new XElement("UnitPrice", 30) ); }
3、刪除節(jié)點(diǎn)
- RemoveAll(): 移除元素的所有內(nèi)容(子節(jié)點(diǎn)和屬性)。
- RemoveAttributes(): 移除元素的屬性。
- ReplaceNodes(): 刪除子節(jié)點(diǎn)。
- Remove(): 移除掉整個(gè)節(jié)點(diǎn)或節(jié)點(diǎn)集合
IEnumerable products = from e in el.Elements("Product") where e.Attribute("ID").Value == "2" select e; if (products.Count() > 0) { products.First().Remove(); } xml.Element("Product").Remove(); // 刪除第一個(gè)Product子元素 xml.Elements("Product").Remove(); // 刪除全部Product子元素 xml.SetElementValue("Product", null); // 刪除第一個(gè)Product子元素 xml.Element("Product").SetElementValue("ProductID", 1); // 修改ProductID子元素 xml.Element("Product").SetElementValue("ProductID", null); // 刪除ProductID子元素
4、屬性操作
//添加屬性: product.Add(new XAttribute("ID", 1)); //修改屬性: product.SetAttributeValue("ID", 2); //刪除屬性: product.Attribute("ID").Remove();
六、使用XPath查詢
為了在LINQ XML中使用XPath查詢,需要添加System.Xml.XPath命名空間。如下:
using Sytem.Xml.XPath;
添加了System.Xml.XPath命名空間,XNode類(lèi)就添加了一系列擴(kuò)展方法。有了這些擴(kuò)展方法,我們可以有兩種選擇處理XML。使我們的應(yīng)用程序可以進(jìn)行一個(gè)平穩(wěn)的移植。
- CreateNavigator方法,這允許我們從一個(gè)現(xiàn)有的XNode對(duì)象創(chuàng)建一個(gè)XPathNavigator對(duì)象。
- XPathEvaluate方法允許對(duì)XNode上的XPath表達(dá)式進(jìn)行計(jì)算。
- XPathSelectElement方法返回第一個(gè)匹配表達(dá)式的元素, XPathSelectElements方法返回所有匹配表達(dá)式的元素。
為了查詢?nèi)缦耎ML數(shù)據(jù):
<category name="Technical"> <category name=".NET"> <books> <book>CLR via C#</book> <book>Essential .NET</book> </books> </category> <category name="Design"> <books> <book>Refactoring</book> <book>Domain Driven Design</book> <book>Patterns of Enterprise Application Architecture</book> </books> </category> <books> <book>Extreme Programming Explained</book> <book>Pragmatic Unit Testing with C#</book> <book>Head First Design Patterns</book> </books> </category>
如何使用XPath查詢XML數(shù)據(jù):
XElement root = XElement.Load("categorizedBooks.xml"); var books = from book in root.XPathSelectElements("http://book") select book; foreach (XElement book in books) { Console.WriteLine((string)book); }
七、XML進(jìn)行轉(zhuǎn)換
1、使用XSLT進(jìn)行轉(zhuǎn)換
string xsl =@"http://www.w3.org/1999/XSL/Transform'>Book Catalog by , "; XElement books = XElement.Load("books.xml"); XDocument output = new XDocument(); using (XmlWriter writer = output.CreateWriter()) { XslCompiledTransform xslTransformer = new XslCompiledTransform(); xslTransformer.Load(XmlReader.Create(new StringReader(xsl))); xslTransformer.Transform(books.CreateReader(), writer); } Console.WriteLine(output);
為了重用轉(zhuǎn)換代碼,可以將轉(zhuǎn)換邏輯封裝到一個(gè)擴(kuò)展方法中
public static class XmlExtensions { public static XDocument XslTransform(this XNode node, string xsl) { XDocument output = new XDocument(); using (XmlWriter writer = output.CreateWriter()) { XslCompiledTransform xslTransformer = new XslCompiledTransform(); xslTransformer.Load(XmlReader.Create(new StringReader(xsl))); xslTransformer.Transform(node.CreateReader(), writer); } return output; } } //使用這個(gè)擴(kuò)展方法 XElement.Load("books.xml").XslTransform(xsl));
2、使用 LINQ to XML 轉(zhuǎn)換 XML
XSL 并不是改變 XML 格式的唯一方式(過(guò)去它是唯一實(shí)際可行的辦法),但今天,LINQ to XML 提供了一個(gè)富有競(jìng)爭(zhēng)力的選擇。要使用 LINQ to XML 進(jìn)行轉(zhuǎn)換,你需要一個(gè)運(yùn)用投影的 LINQ 表達(dá)式。技巧在于投影必須返回一個(gè) XElement 而不是匿名類(lèi)型。
string xmlFile = Server.MapPath("DvdList.xml"); XDocument doc = XDocument.Load(xmlFile); XDocument newDoc = new XDocument( new XDeclaration("1.0", "utf-8", "yes"), new XElement("Movies", from DVD in doc.Descendants("DVD") where (int)DVD.Attribute("ID") < 3 select new XElement[] { new XElement ("Moive", new XAttribute("name", (string)DVD.Element("Title")), DVD.Descendants("Star") ) } ) ); string newFile = Server.MapPath("MovieList.xml"); newDoc.Save(newFile);
結(jié)果:
<?xml version="1.0" encoding="utf-8" standalone="yes"?> <Movies> <Moive name="The Matrix"> <Star>Keanu Reeves</Star> <Star>Laurence Fishburne</Star> </Moive> <Moive name="Forrest Gump"> <Star>Tom Hanks</Star> <Star>Robin Wright</Star> </Moive> </Movies>
基于 LINQ 轉(zhuǎn)換的語(yǔ)法通常要比使用 XSL 樣式表的轉(zhuǎn)換更容易理解,并且更加精確。你也可以很方便的替換為另一個(gè) IEnumable的集合,包括 LINQ to Entities 獲得的結(jié)果集,然后隨意打包成另一種格式的 XML 文檔。
到此這篇關(guān)于C#中Linq To XML的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
c#解析jobject的數(shù)據(jù)結(jié)構(gòu)
這篇文章介紹了c#解析jobject數(shù)據(jù)結(jié)構(gòu)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07c#計(jì)算某段代碼的執(zhí)行時(shí)間實(shí)例方法
在本篇文章里我們給大家整理了關(guān)于c#計(jì)算某段代碼的執(zhí)行時(shí)間的方法和經(jīng)驗(yàn),有興趣的朋友們學(xué)習(xí)下。2019-02-02c#編寫(xiě)webservice服務(wù)引用實(shí)例分享
c#編寫(xiě)webservice服務(wù)引用實(shí)例分享,大家參考使用吧2013-12-12C#實(shí)現(xiàn)塊狀鏈表的項(xiàng)目實(shí)踐
這篇文章主要介紹了C#實(shí)現(xiàn)塊狀鏈表的項(xiàng)目實(shí)踐,通過(guò)定義塊和鏈表類(lèi),利用塊內(nèi)元素引用實(shí)現(xiàn)塊與塊之間的鏈接關(guān)系,從而實(shí)現(xiàn)對(duì)塊狀鏈表的遍歷、插入和刪除等操作,感興趣的可以了解一下2023-11-11使用C#來(lái)編寫(xiě)一個(gè)異步的Socket服務(wù)器
這篇文章主要介紹了使用C#來(lái)編寫(xiě)一個(gè)異步的Socket服務(wù)器,通過(guò)無(wú)阻塞機(jī)制來(lái)獲取更高的處理效率,需要的朋友可以參考下2015-07-07基于Silverlight DataGrid中無(wú)代碼設(shè)置開(kāi)始與結(jié)束日期DatePicker的實(shí)現(xiàn)方法
本篇文章是對(duì)Silverlight DataGrid中無(wú)代碼設(shè)置開(kāi)始與結(jié)束日期DatePicker的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05unity實(shí)現(xiàn)延遲回調(diào)工具
這篇文章主要為大家詳細(xì)介紹了unity實(shí)現(xiàn)延遲回調(diào)工具,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09