Linq To XML總結

語言: CN / TW / HK
  • C#使用linq to xml完成對XML檔案的建立、增加、刪除、修改、查詢

1、XML基本概述

XML檔案是一種常用的檔案格式,例如WinForm裡面的app.config以及Web程式中的web.config檔案,還有許多重要的場所都有它的身影。Xml是Internet環境中跨平臺的,依賴於內容的技術,是當前處理結構化文件資訊的有力工具。XML是一種簡單的資料儲存語言,使用一系列簡單的標記描述資料,而這些標記可以用方便的方式建立,雖然XML佔用的空間比二進位制資料要佔用更多的空間,但XML極其簡單易於掌握和使用。微軟也提供了一系列類庫來倒幫助我們在應用程式中儲存XML檔案。

“在程式中訪問進而操作XML檔案一般有兩種模型,分別是使用DOM(文件物件模型)和流模型,使用DOM的好處在於它允許編輯和更新XML文件,可以隨機訪問文件中的資料,可以使用XPath查詢,但是,DOM的缺點在於它需要一次性的載入整個文件到記憶體中,對於大型的文件,這會造成資源問題。流模型很好的解決了這個問題,因為它對XML檔案的訪問採用的是流的概念,也就是說,任何時候在記憶體中只有當前節點,但它也有它的不足,它是隻讀的,僅向前的,不能在文件中執行向後導航操作。

三種常用的讀取XML檔案的方法。分別是

①使用XmlDocument

②使用XmlTextReader

③使用Linq to Xml

本文主要討論使用Linq to Xml的方法實現對XML文件的建立、增加、刪除、修改、查詢的操作。

例1:建立XML檔案

string path = "1.xml";

static void Main(string[] args)

{

CreateXml();//建立xml檔案

}

private static void CreateXml()

{

XDocument xdoc = new XDocument();//建立XDocument物件例項

XElement root = new XElement("school");//建立根節點

XElement cls = new XElement("class");//建立class節點

cls.SetAttributeValue("number", "0302");

XElement stu1 = new XElement("student");

stu1.SetAttributeValue("id", "001");

stu1.SetElementValue("name", "張三"); //新增子節點stu1的資料,如姓名張三 

stu1.SetElementValue("gender", "男"); //新增子節點stu1的資料,如性別男 

stu1.SetElementValue("age", "19"); //新增子節點stu1的資料,如年齡19 

//建立子節點class的子節點學生stu2 

XElement stu2 = new XElement("student");

stu2.SetAttributeValue("id", "002"); //新增子節點stu2的屬性,如學號002 

stu2.SetElementValue("name", "李曉梅"); //新增子節點stu2的資料,如姓名李曉梅 

stu2.SetElementValue("gender", "女"); //新增子節點stu2的資料,如性別女 

stu2.SetElementValue("age", "18"); //新增子節點stu2的資料,如年齡18 

cls.Add(stu1); //新增student到class 

cls.Add(stu2); //新增student到class 

root.Add(cls); //新增子節點class到根節點school 

xdoc.Add(root); //新增根節點到XDoucment物件 

xdoc.Save("1.xml"); //使用XML的儲存會自動在xml檔案開始新增:\<?xml version="1.0" encoding="utf-8"?> 

Console.WriteLine("建立XML檔案成功!");

Console.ReadKey();

}

檔案內容:

\<?xml version="1.0" encoding="utf-8"?>

\

\

\

\張三\

\男\

\19\

\

\

\李曉梅\

\女\

\18\

\

\

\

例2:讀取XML檔案

static string path = "1.xml";

static void Main(string[] args)

{

// CreateXml();//建立xml檔案

ReadXml();

}

private static void ReadXml()

{

XDocument xdoc = XDocument.Load(path);//載入XML檔案

XElement rootSchool = xdoc.Root;//獲取根節點

IEnumerable\ xeles = rootSchool.Elements();

foreach (XElement xeleClass in xeles)

{

foreach (XElement xeleStudent in xeleClass.Elements())

{

Console.WriteLine(xeleStudent.Name); //獲取節點名 

Console.WriteLine(xeleStudent.Attribute("id").Value); //獲取屬性值 

Console.WriteLine(xeleStudent.Element("name").Value); //下面3行是獲取資料 

Console.WriteLine(xeleStudent.Element("gender").Value);

Console.WriteLine(xeleStudent.Element("age").Value);

}

}

Console.ReadKey();

}

例3:增加資料

private static void AddData()

{

XDocument xdoc = XDocument.Load(path);

XElement xeleRoot = xdoc.Root;

//在已存在的節點上新增屬性和資料 

XElement xeleClass = xeleRoot.Element("class");

XElement xeleStu3 = new XElement("student");

xeleStu3.SetAttributeValue("id", "005");

xeleStu3.SetElementValue("name", "王五");

xeleStu3.SetElementValue("gender", "男");

xeleStu3.SetElementValue("age", "40");

xeleClass.Add(xeleStu3);

xdoc.Save("1.xml");

Console.WriteLine("新增xml成功");

Console.ReadKey();

}

執行結果:

private static void AddData()

{

XDocument xdoc = XDocument.Load(path);

XElement xeleRoot = xdoc.Root;

//在已存在的節點上新增屬性和資料 

XElement xeleClass = xeleRoot.Element("class");

XElement xeleStu3 = new XElement("student");

xeleStu3.SetAttributeValue("id", "005");

xeleStu3.SetElementValue("name", "王五");

xeleStu3.SetElementValue("gender", "男");

xeleStu3.SetElementValue("age", "40");

xeleClass.Add(xeleStu3);

xdoc.Save("1.xml");

Console.WriteLine("新增xml成功");

Console.ReadKey();

}

例4:刪除資料

private static void DeleteData()

{

XDocument xdoc = XDocument.Load("1.xml");

XElement xeleRoot = xdoc.Root;

//刪除根節點的直接子節點

XElement xeleClass = xeleRoot.Elements("class").Where(x => x.Attribute("number").Value == "0302").Single(); //拉姆達表示式

xeleClass.Remove();

//刪除根節點的直接子節點的下一級節點

//XElement xeleClass = xeleRoot.Elements("class").Where(x => x.Attribute("number").Value == "0302").Single(); //獲取班級號為0302的直接子節點

//XElement xeleStudent = xeleClass.Elements("student").Where(x => x.Attribute("id").Value == "001").Single(); //獲取學號為001的直接子節點的下一級節點

//xeleStudent.Remove();

xdoc.Save("1.xml");

Console.WriteLine("刪除節點成功!");

Console.ReadKey();

}

例5:修改資料

private static void Update()

{

XDocument xdoc = XDocument.Load("1.xml");

XElement xeleRoot = xdoc.Root;

XElement xeleClass = xeleRoot.Elements("class").Where(x => x.Attribute("number").Value == "0302").Single(); //獲取班級號為0302的直接子節點

XElement xeleStudent = xeleClass.Elements("student").Where(x => x.Attribute("id").Value == "001").Single(); //獲取學號為001的直接子節點的下一級節點

xeleStudent.SetAttributeValue("id", "008");

xeleStudent.SetElementValue("name", "邦德");

xeleStudent.SetElementValue("gender", "爺們");

xeleStudent.SetElementValue("age", "39");

xdoc.Save("1.xml");

Console.WriteLine("修改成功!");

Console.ReadKey();

}

  • 查詢指定元素

Xml的內容:

\<?xml version="1.0" encoding="utf-8" standalone="yes"?>

\

\

\張三\

\男\

\20\

\

\

\李四\

\女\

\18\

\

\

程式碼:

private void LoadData(string idcard)

{

string xmlFilePath = "Employee.xml";//xml檔案存放的路徑

XElement xes = XElement.Load(xmlFilePath);//載入xml檔案

if (idcard == "")

{

//查詢所有的元素

var elements = from ee in xes.Elements("Person")

select new

{

姓名 = ee.Element("Name").Value,

性別 = ee.Element("Sex").Value,

年齡 = ee.Element("Age").Value,

身份證號 = ee.Attribute("IDCard").Value

};

dataGridView1.DataSource = elements.ToList();

}

else

{

//查詢指定名稱的元素

var elements = from ee in xes.Elements("Person")

where ee.Attribute("IDCard").Value == idcard

select new

{

姓名 = ee.Element("Name").Value,

性別 = ee.Element("Sex").Value,

年齡 = ee.Element("Age").Value,

身份證號 = ee.Attribute("IDCard").Value

};

dataGridView1.DataSource = elements.ToList();

}

}

private void button1_Click(object sender, EventArgs e)

{

LoadData(comboBox1.Text);

}

  • 遍歷指定節點的所有物件

private void Form1_Load(object sender, EventArgs e)

{

XDocument doc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), new XElement("People",

new XElement("Person",

new XAttribute("IDCard", "22030219771012"),

new XComment("身份證號是唯一的"),

new XElement("Name", "張三"),

new XElement("Sex", "男"),

new XElement("Old", 20),

new XText("這是物件文字"))));

IEnumerable\ nods = doc.Element("People").Elements("Person").Nodes();

foreach (XNode nod in nods)

{

string s = nod.ToString();

label1.Text += s + "\n";

}

}

  • 返回指定節點下的註釋

private void Form1_Load(object sender, EventArgs e)

{

XDocument doc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), new XElement("People",

new XElement("Person",

new XAttribute("IDCard", "22030219771012"),

new XComment("身份證號是唯一的"),

new XElement("Name", "張三"),

new XElement("Sex", "男"),

new XElement("Old", 20),

new XText("這是物件文字"))));

IEnumerable\ nods = doc.Element("People").Elements("Person").Nodes().OfType\();

foreach (XNode nod in nods)

{

string s = nod.ToString();

label1.Text += s + "\n";

}

}

  • 使用Descendants方法訪問指定元的父節點

XDocument類的Descendants方法: 該方法用來按文件順序返回此文件或元素的經過篩選的子代元素的集合,集合中只包括具有匹配XName的元素。

語法:public IEnumerable\ Descendants(XName name)

private void Frm_Main_Load(object sender, EventArgs e)

{

//使用LINQ建立xml檔案的內容

XDocument doc = new XDocument(

new XDeclaration("1.0", "utf-8", "yes"),

new XElement("People",

new XElement("Person",

new XAttribute("IDCard", "22030219771012***"),

new XElement("Name", "張三"),

new XElement("Sex", "男"),

new XElement("Age", 34)

),

new XElement("Person",

new XAttribute("IDCard", "22030219901111***"),

new XElement("Name", "李四"),

new XElement("Sex", "女"),

new XElement("Age", 20)

)

)

);

XElement eleName = doc.Descendants("Name").Where(itm => itm.Value == "張三").First();//查詢值等於"張三"的\元素

XElement xe = eleName.Parent;//獲取父節點

label1.Text=xe.ToString();//將父節點的內容輸出

}

  • 返回節點集合中每個節點的所有上級節點

本例只要用到Extensions類的Ancestors擴充套件方法和XElement類的Name屬性。

  1. Extensions類的Ancestors擴充套件方法用來返回元素集合,其中包含源結合中每個節點的上級。語法格式:public static IEnumerable\  Ancestors\(this IEnumerable\ source) where T:XNode

程式碼如下:

private void Frm_Main_Load(object sender, EventArgs e)

{

//使用LINQ建立XML

XDocument doc = new XDocument(

new XDeclaration("1.0", "utf-8", "yes"),

new XElement("People",

new XElement("Person",

new XAttribute("IDCard", "22030219771012***"),

new XElement("Name", "張三"),

new XElement("Sex", "男"),

new XElement("Age", 34)

),

new XElement("Person",

new XAttribute("IDCard", "22030219901111***"),

new XElement("Name", "李四"),

new XElement("Sex", "女"),

new XElement("Age", 20)

)

)

);

IEnumerable\ elements = doc.Element("People").Descendants("Name");        //取所有的Name元素

label1.Text="顯示源元素\n";

foreach (XElement element in elements)//遍歷輸出Name元素

{

label1.Text += "元素名稱:" + element.Name + "   元素值:" + element.Value + "\n";

}

label1.Text += "顯示每個源元素的祖先元素\n";

foreach (XElement element in elements.Ancestors())//遍歷輸出每個Name元素的所有上級節點

{

label1.Text += "元素名稱:" + element.Name + "   元素值:" + element.Value + "\n";

}

}

結果:

  • 返回節點集合中每個節點的所有下級節點

private void Frm_Main_Load(object sender, EventArgs e)

{

//使用LINQ建立XML

XDocument doc = new XDocument(

new XDeclaration("1.0", "utf-8", "yes"),

new XElement("People",

new XElement("Person",

new XAttribute("IDCard", "22030219771012***"),

new XElement("Name", "張三"),

new XElement("Sex", "男"),

new XElement("Age", 34)

),

new XElement("Person",

new XAttribute("IDCard", "22030219901111***"),

new XElement("Name", "李四"),

new XElement("Sex", "女"),

new XElement("Age", 20)

)

)

);

IEnumerable\ elements = doc.Element("People").Elements("Person");//查詢Person元素

label1.Text += "顯示源元素\n";

foreach (XElement element in elements)//遍歷並輸出Person元素

{

label1.Text += "元素名稱:" + element.Name + "   元素值:" + element.Value + "\n";

}

label1.Text += "顯示每個源元素的子孫節點\n";

foreach (XNode nod in elements.DescendantNodes())//遍歷並輸出所有的下級節點

{

label1.Text += "子孫節點:" + nod.ToString() + "\n";

}

}

  • 返回原宿集合中每個元素的所有屬性

private void Frm_Main_Load(object sender, EventArgs e)

{

//使用LINQ建立XML

XDocument doc = new XDocument(

new XDeclaration("1.0", "utf-8", "yes"),

new XElement("People",

new XElement("Person",

new XAttribute("Name", "張三"),

new XAttribute("Sex", "男"),

new XAttribute("Age", 34),

new XElement("IDCard", "22030219771012***")

),

new XElement("Person",

new XAttribute("Name", "李四"),

new XAttribute("Sex", "女"),

new XAttribute("Age", 20),

new XElement("IDCard", "22030219901111***")

)

)

);

IEnumerable\ elements = doc.Element("People").Elements("Person");//查詢Person元素

label1.Text="顯示源元素\n";

foreach (XElement element in elements)//遍歷輸出Person元素

{

label1.Text += "元素名稱:" + element.Name + "   元素值:" + element.Value + "\n";

}

label1.Text += "顯示每個源元素的屬性\n";

foreach (XAttribute attr in elements.Attributes())//遍歷每個源元素的屬性

{

label1.Text += "屬性名稱:" + attr.Name + "   屬性值:" + attr.Value + "\n";

}

}

  • 替換指定節點下的所有元素

private void Frm_Main_Load(object sender, EventArgs e)

{

string path = "new.xml";//取XML檔案的全路徑

XElement xe = XElement.Load(path);//載入XML檔案

//用LINQ查詢要修改的元素

IEnumerable\ element = from ee in xe.Elements("Person")

where ee.Attribute("IDCard").Value == "22030219901111***"

&& ee.Element("Name").Value == "李四"

select ee;

if (element.Count() > 0)//存在要修改的元素

{

XElement first = element.First();//取第一個元素

//全部替換成新的節點

first.ReplaceAll(

new XAttribute("IDCard", "22030219891111XXX"),

new XElement("Name", "李麗"),

new XElement("Sex", "女"),

new XElement("Age", 21)

);

}

xe.Save(path);//儲存檔案

webBrowser1.Url = new Uri(Application.StartupPath + "\\" + path);//在窗體中顯示XML檔案內容

}

  • 將XML檔案中的屬性轉換為元素

private void Frm_Main_Load(object sender, EventArgs e)

{

string xmlFilePath = Application.StartupPath+"\\new.xml";//取XML檔案的全路徑

XElement xe = XElement.Load(xmlFilePath);//載入XML檔案

//用LINQ查詢要操作的元素

IEnumerable\ element = from ee in xe.Elements("Person")

where ee.Attribute("IDCard").Value == "22030219901111***"

&& ee.Element("Name").Value == "李四"

select ee;

if (element.Count() > 0)                                                        //存在要操作的元素

{

XElement first = element.First();

XAttribute attribute = first.Attribute("IDCard");//取身份證號屬性

//新增一個名稱和值都與屬性一樣的子元素

first.AddFirst(

new XElement(attribute.Name, attribute.Value)

);

first.RemoveAttributes();//刪除身份證號屬性

}

xe.Save(xmlFilePath);//儲存XML檔案

webBrowser1.Url = new Uri(xmlFilePath);//在窗體中顯示XML內容

}