C#每日一課(三十九)

LINQ to SQL
LINQ to SQL提供了一種把關係型數據庫映射到編程語言表示的對象模型,使用得開發人員可以通過編程語言直接操作數據庫,數據庫的訪問由此變得更加快捷和高效。

  • 對象模型的原理
    與LINQ to DataSet一樣它也是ADO.NET和LINQ結合的產物。它把編程對象和數據庫關係模型直接映射,比LINQ to DataSet更進一步。
    在LINQ to SQL中,開發人員不用向數據庫發出SQL命令,而是在對象模型中直接更改值或執行方法。當開發人員通過對象模型執行操作時,LINQ to SQL把請求轉換成SQL命令,然後把這些命令發送到數據庫,得到返回數據庫服務器的操作結果後,再把這些結果傳遞給到對象模型。
    模型
    由於對象模型和關係型數據庫中每個元素之間有一種一對一的映射關係,開發人員纔可以通過對象模型來訪問數據庫。
    數據庫表DataTable,被映射成爲C#類
    數據庫表的列(字段),被映射到C#類的成員(屬性)
    數據庫表的外鍵關係(Relation)被映射成爲C#類的關聯
    數報庫表中的存儲過程被或函數被映射成到C#類的方法

創建對象模型的常用3種方法:
1.對象關係設計器:O/R設計器
2.SQLMetal代碼生成工具,它的可操作性差,無界面
3.代碼編輯器,這個方法編碼工作量大,容易出錯

  • O/R設計器
    在Visual Studio2017中沒有LINQ to SQL模板的話,則可以使用“工具”-“獲取工具和功能”-“單個組件”中添加LINQ to SQL即可。

在“數據源”中,可以添加當前項目需要綁定的數據源
在界面中添加DataGridView,並綁定對應的數據

LINQ to XML

  • XML
    extensible Markup Language,可擴展標記語言,廣泛用於網絡、數據傳輸和存儲、數據庫等領域。
    LINQ to XML提供了一套通過LINQ在內存中操作XML數據的編程接口,相當於更新和重新設計的文檔對象模型XML編程接口。
  • LINQ to XML概述
    LINQ to XML提供使用LINQ在內存中操作XML數據的編程接口,它提供比DOM更簡潔的開發接口。還可以通過LINQ直接對內存中的XML數據進行查詢或更改,代碼更加簡潔和高效。
  • 關於LINQ to XML
    XML和HTML一樣,是一種標識語言。和HTML相比,XML具有可擴展性、面向對象等特性。
    在.NET Framework中,開發人員或以通過System.Xml命名空間提供的相關類庫完成XML數據的讀寫。還有一個System.Xml.Linq命名空間,這個命名空間提供了一套新的讀寫XML數據的編程接口——LINQ to XML。

把XML文檔置於內存中,在查詢、修改xml文檔後可以把它另存爲文件,也可以把它序列化然後通過網絡發送。
LINQ to XML最重要的優勢在於它與LINQ的集成,可以對內存XML文檔編寫查詢,從而檢索元素和屬性的集合。
通過把查詢結果用作XElement和XAttribute對象構造函數的參數,實現了一種功能強大的創建XML樹的方法。這種方法稱爲“函數構造”。利用這種方法,開發人員可以方便把XML樹從一種形態轉爲另一種形態。

LINQ to XML主要類:
1.Extensions:提供了所有LINQ to XML類的擴展方法
2.XAttriute:這個類表示一個XML節點的屬性
3.XCData:這個類表示一個包含CDATA的文本節點
4.XComment:這個類表示一個XML文件的註釋
5.XContainer:表示XML文件中可以包含其它節點的結節
6.XElement:這個類從XContainer類派生,表示一個XML元素
7.XDocument:這個類從XContainer類派生,表示的是一個完整的XML文檔
8.XDocumentType:這個類表示XML文檔的類型定義DTD
9.XDeclaration:這個表示一個XML文件的XML聲明,通常出現在XML文件頭部
10.XName:這個類表示XML文件中元素或屬性的名稱
11.XText:這個類表示一個文本節點
12.XNamespace:這個類表示XML命名空間
13.XNode:這個類表示XML樹中節點的抽象概念
14.XNodeDocumentOrderComparer:這個類表示比較結點的文檔順序的功能
15.XNodeEqualityComparer:這個類用來比較節點確定是否相等
16.XObject:這個類用來表示XML樹中節點或屬性
17.XObjectChangeEventArgs:這個類提供有關XObject類屬性Changing和Changed事件的數據
18.XProcessingInstruction:這個類用來表示一個XML的處理指令
19.XStreamingElement:這個類表示支持延遲流輸出的XML樹中的元素
20.LoadOptions:這個枚舉類型指定分析XML時的加載選項,包含None、PreserveWhitespace、SetBaseUri和SetLineInfo4個或選值
21.SaveOptions:這個枚舉指定序列化選項,包含None、DisableFormatting兩個可選值
22.XObjectChange:這個枚舉指定爲XObject引發事件時的事件類型,包含Add、Remove、Name和Value這4個可選值
注意:在使用類和枚舉的時候要先引用System.Xml和System.Xml.Linq命名空間。

  • DOM 與 LINQ to XML
    命名空間System.Xml提供了對DOM的支持。
    使用DOM與LINQ來生成XML的方法如下:
  • DOM生成
//創建XmlDocument表示XML
XmlDocument doc = new XmlDocument();
//創建根節點BookList
XmlElement bookList = doc.CreateElement("BookList");
XmlElement book, auth;
//創建子節點Book-1
book = doc.CreateElement("Book");
book.SetAttribute("Name", "Book-1");
auth = doc.CreateElement("Author");
auth.InnerText = "Author-1";
book.AppendChild(auth);
bookList.AppendChild(book);
//創建子節點Book-2
book = doc.CreateElement("Book");
book.SetAttribute("Name", "Book-2");
auth = doc.CreateElement("Author");
auth.InnerText = "Author-2";
book.AppendChild(auth);
bookList.AppendChild(book);
//把根節點添加到文檔
doc.AppendChild(bookList);
/*FileStream f = null;
  try
  {
     f = File.Create(@"D:\book1.xml");
  }
  catch (Exception e)
  {
     Console.WriteLine(e.Message);
  }
  finally
  {
     f.Close();
  }*/
//這個方法會自動創建對應的文檔
doc.Save(@"D:\book1.xml");

生成的xml文件如下:
運行結果

  • LINQ生成
XElement bookLst =
    new XElement("BookList", //根節點 BookList 
        new XElement[]
        {
            new XElement("Book",//第 1 個節點 Book-1
               new object[]{ //屬性 Name 和子元素 Author 
                   new XAttribute("Name", "Book-1"),
                   new XElement("Author", "Author-1")}),
            new XElement("Book", //第 2 個節點 Book-2 
               new object[]{ //屬性 Name 和子元素 Author 
                   new XAttribute("Name", "Book-2"),
                   new XElement("Author", "Author-2")}),
         }
     );

bookLst.Save(@"D:\book2.xml");

運行結果

比較項 DOM LINQ
直接使用xml元素 必須在xml文檔上下文中創建xml節點,包括節點的元素和屬性 可以直接使用xml元素和屬性,可不通過XML文檔對象創建xml元素,把xml元素序列化到文件流
構造新的XML樹或節點 代碼量大可讀性不好 代碼簡單,xml結構清晰,可讀性好
跨文檔使用xml元素 需要加載多個xml文檔,在各自的上下文中使用xml元素 不需要加載多個xml文檔,直接使用xml元素,除非在文檔根級別添加xml元素
修改節點名稱 只有在創建時確定,創建完後不可以修改 可以通過XName類修改任意xml節點或屬性的名稱
對片段的支持 提供XmlDocumentFragment類支持xml片段 通過XNode轉化IEnumerable進行查詢實現
  • 構造XML樹
    構造xml文檔是最基本的xml文檔操作之一,在進行xml文檔數據操作之前,都需要先在內存中創建XML樹,然後纔對其進行操作。

1.構造簡單的XML元素
在LINQ to XML中使用XElement類表示XML文檔中的元素,XElement類提供多個不同版本的構造函數。
1.public XElement(XName name)
2.public XElement(XElement element)
3.public XElement(XName name,object content)

參數name表示包含元素名稱的XName對象。
參數element表示新Xml元素的源元素,這個函數創建一個源元素的深層副本。
參數content是object類型,表示元素的內容,所以空強以是任何的數據類型,而顯示的內容則是這個對象的ToString()方法所返回的字符串。

XName類並沒有提供構造函數,所以不可以創建XName類型對象作爲參數傳入XElement構造函數,但是是存在一個從字符串到XName類型的隱式轉換,所以只需要把一個string類型參數傳入到XElement構造函數即可。

XElement類的ToString()方法返回元素的文本形式,包括製表符和空白。
如下實例,新建一個自定義類並把使用XElement構造函數生成對應的XML元素

//創建一個UserClass類
public class UserClass
{
    private string name;
    private int age;
    public UserClass(int age, string name)
    {
        this.age = age;
        this.name = name;
    }
    //重寫ToString()方法
    public override string ToString()
    {
        return string.Format("{0}的年齡是:{1}", name, age);
    }
}

static void CreateElement()
{
    //創建簡單的XML元素,使用XElement(XName)的使用
    XElement ele1 = new XElement("User");
    Console.WriteLine("ele1:\n"+ele1);
    //創建簡單的XML元素,使用XElement(XElement),做深層的副本
    XElement ele2 = new XElement(ele1);
    Console.WriteLine("ele2:\n" + ele2);
    //創建一個帶內容的XML元素,使用XElement(XName,object)
    XElement ele3 = new XElement("name", "名稱");
    Console.WriteLine("ele3:\n" + ele3);
    //創建元素內容類型爲float的XML元素,使用XElement(XName,object)
    XElement ele4 = new XElement("PI", 3.1415f);
    Console.WriteLine("ele4:\n" + ele4);
    //創建元素內容類型爲DateTime的XML元素,使用XElement(XName,object)
    XElement ele5 = new XElement("DateTime", DateTime.Now);
    Console.WriteLine("ele5:\n" + ele5);
    //創建元素內容類型爲匿名類類型的XML元素,使用XElement(XName,object)
    XElement ele6 = new XElement("AnoymousClass", new { x = 1.01, y = 2.01, z = 3.33 });
    Console.WriteLine("ele6:\n" + ele6);
    //創建元素內容類型爲自定義類類型的XML元素,使用XElement(XName,object)
    UserClass uc = new UserClass(20, "謝聲");
    XElement ele7 = new XElement(uc.GetType().Name,uc);
    Console.WriteLine("ele7:\n" + ele7);
}

在Main方法中做如下調用:

CreateElement();
Console.ReadKey();

編譯運行結果如下:
運行結果

2.構造具有屬性的xml元素
在LINQ to XML中,使用XAttribute類表示一個XML元素的屬性。它包括一個(名稱,值)數據對,用來表示這個屬性的名稱和值。任何xml元素都包含一個XAttribute列表,用來表示它所包含的所有屬性。同一個XML元素所包含的屬性名是不可以重複的。
XAttribute類構造函數可以創建XML屬性
1.public XAttribute(XName name,object value)
2.public XAttribute(XAttribute other)
參數 name 表示屬性(Attribute)的名稱,其是XName類型,同樣只需使用字符串參數即可。參數value表示屬性的值,它是object類型,所以屬性的值可以是任何類型。

第二個版本用來創建一個已有屬性的深層副本,參數other表示要被複制的屬性對象。

在LINQ to XML中,用XElement類構造函數創建XML元素,結合XAttribute類可以創建帶有屬性的XML元素。
XElement類提供了一個具有可變參數的構造函數,用來創建各種複雜樣式的XML元素
public XElement(XNmae name,params object[] content)
name:它是一個XName對象,表示元素的名稱
content:它是一個可變參數,爲object類型,可以傳入任何類型的參數
當要創建具有屬性的XML元素,就需要使用上面的XElement構造函數,傳入的content爲XAttribute類對象時,則表示這個元素的一個屬性,但是不能在同一個XElement對象中創建兩個以上具有同名稱的XAttribute類的對象。

創建一個類並創建一個生成屬性的方法

//創建一個Userclass類
public class UserClass
{
    private string Name;
    private int Age;

    public UserClass(string name, int age)
    {
        Name = name;
        Age = age;
    }
    //重寫ToString()
    public override string ToString()
    {
        return string.Format("{0}的年齡是:{1}", Name, Age);
    }
}

//XML屬性創建
static void CreateXmlAttributeEle()
{
    //創建類型爲string的屬性,使用XAttribute(XName,object)方法
    XAttribute attr1 = new XAttribute("Name", "xiesheng");
    Console.WriteLine("attr1:"+attr1);
    //創建屬性的深層的副本,使用XAttribute(XAttribute)
    XAttribute attr2 = new XAttribute(attr1);
    Console.WriteLine("attr2:" + attr2);
    //創建類型爲DateTime的屬性,使用XAttribute(XName,object)
    XAttribute attr3 = new XAttribute("DateTime", DateTime.Now);
    Console.WriteLine("attr3:" + attr3);
    //創建自定義類的屬性,使用XAttribute(XName,object)
    XAttribute attr4 = new XAttribute("UserClass",new UserClass("謝聲", 30));
    Console.WriteLine("attr4:" + attr4);
    //創建一個Xml元素,傳入XAttribute參數,使用XElement(XName,object[])
    XElement ele1 = new XElement("Student", attr1);
    Console.WriteLine("ele1:\n" + ele1);
    //傳入一個XAttribute數組
    XAttribute[] attrArray = { attr3, attr4 };
    XElement ele2 = new XElement("Student_time", attrArray);
    Console.WriteLine("ele2:\n" + ele2);
}

在Main方法中做如下調用測試

CreateXmlAttributeEle();
Console.ReadKey();

編譯運行的結果如下:
運行結果

3.構造有子元素的XML元素
一個xml元素,一般是包含一個或多個子元素,可以通過XElement的可變參數版本構造函數創建具有子元素的xml元素。當傳入的參數是XElement類型的時候,這個參數則是所有xml元素的子元素。注意:xml元素的子元素的排列順序與它們作爲參數傳入的順序相同,當傳入的是數組時,數組中元素可以看成從0-n的順序展開的多個參數來看待。
新增一個創建帶子元素的XML元素的方法

//創建帶有子元素的xml元素
static void CreateSubElement()
{
    //直接在構造函數中創建XML文檔
    XElement userList1 = new XElement("UserList",
        new XElement("User",
            new XElement("Name","張三"),
            new XElement("Age",30)
            ),
        new XElement("User",
            new XElement("Name", "李四"),
            new XElement("Age", 20)
            )
        );
    //先創建兩個用戶的xml元素
    XElement user1 = new XElement("User",
        new XElement("Name","張三"),
        new XElement("Age",30));
    XElement user2 = new XElement("User",
        new XElement("Name", "李四"),
        new XElement("Age", 20));
    //創建帶兩個用戶信息的xml元素
    XElement userList2 = new XElement("UserList", user1, user2);
    //使用兩個用戶信息數組來創建xml元素
    XElement[] xes = { user1, user2 };
    XElement userList3 = new XElement("UserList", xes);
    //輸出結果
    Console.WriteLine("userList1:\n" + userList1);
    Console.WriteLine();
    Console.WriteLine("userList2:\n" + userList2);
    Console.WriteLine();
    Console.WriteLine("userList3:\n" + userList3);
}

在Main方法中調用這個方法進行測試

CreateSubElement();
Console.ReadKey();

編譯運行結果如下:
運行結果

4.使用XElement類構造XML樹
在XML元素中,通常包含元素、屬性、內容等多個特性,可以使用XElement類的可變參數的構造函數同時傳入類型爲XAttribute和XElement則可以,在傳入多個參數中,如果參數是XAttribute則這個參數就是XML元素的屬性,如果參數爲XElement類型時,這個參數就是xml元素的子元素,如果傳入的是int,string,float等類型時,這些參數的字符串形式按照先後順序連接起來作爲元素的內容。
新增一個創建XML樹的方法

//創建XML樹
static void CreateXMLTree()
{
    //創建用戶1
    XElement user1 = new XElement("User",
        new XAttribute("Name", "張三"),
        new XAttribute("Age", 30));
    //創建用戶2
    XElement user2 = new XElement("User",
        new XAttribute("Name", "李四"),
        new XAttribute("Age", 20));
    //創建一個具有多個用戶列表的XML元素
    XElement userList = new XElement("UserList", "string content",
        user1, user2, new XAttribute("Count", 2), 100);
    Console.WriteLine("UserList:\n" + userList);
}

在Main方法中做如下調用測試

CreateXMLTree();
Console.ReadKey();

編譯運行結果如下:
運行結果

  • 查詢XML樹
    XElement類通過Elements和Attributes提供當前XML元素的子元素和屬性集合,通過這兩個集合則可以對XML文檔中的元素進行查詢操作。

1.查找具有特定屬性的元素
用來獲取XML元素中的屬性和子元素的方法:
a.Element():獲取當前xml元素的第一個具有指定名稱的子元素
b.Elements():獲取當前xml元素的所有子元素,或具有指定名稱的所有子元素,返回的類型爲IEnumerable元素集合
c.Attribute():獲取當前xml元素具有指定名稱的屬性
d.Attributes():獲取當前xml元素的所有屬性,或具有指定名稱的屬性,返回類型爲IEnumerable屬性集合
創建一個UserList.xml的xml文檔
新建一個創建xml文檔的方法:

//創建xml文檔
static void CreateXMLByLINQ()
{
    XElement userList =
        new XElement("UserList",
        //節點Count
        new XElement("Count",4),
        //創建第一個節點User
        new XElement("User",new XAttribute("Name","張三"),
            new XAttribute("Age","23"),
            new XElement("Sex","Male"),
            new XElement("Mobile","13012345678")),
        //創建第二個節點User
        new XElement("User", new XAttribute("Name", "李四"),
            new XAttribute("Age", "20"),
            new XElement("Sex", "Male"),
            new XElement("Mobile", "130223456789")),
        //創建第三個節點User
        new XElement("User", new XAttribute("Name", "李敏"),
            new XAttribute("Age", "18"),
            new XElement("Sex", "Female"),
            new XElement("Mobile", "13323445678")),
        //創建第四個節點User
        new XElement("User", new XAttribute("Name", "王霞"),
            new XAttribute("Age", "22"),
            new XElement("Sex", "Female"),
            new XElement("Mobile", "13613344678"))
        );
    userList.Save(@"D:\UserList.xml");
}

在Main方法中調用創建xml文檔的方法

CreateXMLByLINQ();
Console.WriteLine("xml文檔創建完成");
Console.ReadKey();

編譯運行結果如下:
運行結果
生成xml文檔如下:

<?xml version="1.0" encoding="utf-8"?>
<UserList>
  <Count>4</Count>
  <User Name="張三" Age="23">
    <Sex>Male</Sex>
    <Mobile>13012345678</Mobile>
  </User>
  <User Name="李四" Age="20">
    <Sex>Male</Sex>
    <Mobile>130223456789</Mobile>
  </User>
  <User Name="李敏" Age="18">
    <Sex>Female</Sex>
    <Mobile>13323445678</Mobile>
  </User>
  <User Name="王霞" Age="22">
    <Sex>Female</Sex>
    <Mobile>13613344678</Mobile>
  </User>
</UserList>

要對xml文檔進行查詢處理需要做如下工作:
1.使用XElement類中的Load()方法把文檔加載到內存
2.使用Elements(),Attributes(),Element(),Attribute()方法查找所有或指定元素或屬性

程序中添加一個查詢元素和屬性的方法如下 :

//查詢xml文檔中元素或屬性
static void QueryAttributeElement()
{
    //從文件中加載xml數據到內存中
    XElement root = XElement.Load(@"D:\UserList.xml");
    IEnumerable<XElement> Users = root.Elements("User");
    //查詢所有的User
    var userList =
        from ele in Users select ele;
    foreach (var item in userList)
    {
        Console.WriteLine(item);
    }
    //查詢所有User的姓名
    var nameList =
        from ele in Users select ele.Attribute("Name");
    foreach (string name in nameList)
    {
        Console.Write("{0},",name);
    }
    Console.WriteLine();
    //查詢所有年齡大於等於20歲的User
    var ageList =
        from ele in Users
        where int.Parse(ele.Attribute("Age").Value) >= 20
        select new { Name = ele.Attribute("Name"), Age = ele.Attribute("Age") };
    foreach (var item in ageList)
    {
        Console.WriteLine(item);
    }
}

在Main方法中做如下調用

QueryAttributeElement();
Console.ReadKey();

編譯運行結查如下:
運行結果

2.查找具有特定子元素的元素
在LINQ to XML中,可以通過XElement類的Elements()方法進行子元素的名稱過濾,通過Element()方法進行指子元素的獲取。
Elements()返回的元素是IElements類型,可以用where子句對它的元素進行條件判斷,從而實現元素的過濾,即查找到滿足指這下條件的子元素。
在程序中添加如下方法進行子元素的查詢

//查找指定子元素
static void QuerySubElement()
{
    //從文件中加載xml文檔到內存中
    XElement root = XElement.Load(@"D:\UserList.xml");
    IEnumerable<XElement> users = root.Elements("User");
    var query1 =
        from ele in users
        from ele2 in ele.Elements()
        where "Sex".Equals(ele2.Name.LocalName)
        select new { name = ele.Attribute("Name").Value, sex = ele2.Value };
    //輸出查詢結果
    foreach (var item in query1)
    {
        Console.WriteLine(item);
    }
    //查詢性別爲Female的用戶
    var query2 =
        from ele in users
        where "Female".Equals(ele.Element("Sex").Value)
        select ele;
    Console.WriteLine("性別爲Female的用戶:");
    foreach (var item in query2)
    {
        Console.WriteLine(item);
    }
}

在Main方法中做如下調用

QuerySubElement();
Console.ReadKey();

編譯運行的結果如下:
運行結果

3.對xml元素進行排序
對xml元素的查詢結果進行排序使用orderby子句完成,只是排序的原則是通過XElement類Attribute()和Element()等方法獲得的XML元素數據。
在程序中新增排序方法如下:

//對xml元素進行排序
static void OrderByElement()
{
    //加載xml文檔到內存
    XElement root = XElement.Load(@"D:\UserList.xml");
    IEnumerable<XElement> users = root.Elements("User");
    var query1 =
        from ele in users
        orderby ele.Attribute("Age").Value descending //按年齡從大到小排序
        select new { name = ele.Attribute("Name").Value, age = ele.Attribute("Age") };
    Console.WriteLine("按年齡從大到小排序:");
    foreach (var item in query1)
    {
        Console.WriteLine(item);
    }
    //對年齡大於等於20的用戶,按年齡從大到小排序
    var query2 = 
        from ele in users
        where int.Parse(ele.Attribute("Age").Value)>=20
        orderby ele.Attribute("Age").Value descending
        select new { name = ele.Attribute("Name").Value, age = ele.Attribute("Age") };
    Console.WriteLine("年齡大於等於20歲的用戶按年齡從大到小排序:");
    foreach (var item in query2)
    {
        Console.WriteLine(item);
    }
}

在Main方法中做如下調用:

OrderByElement();
Console.ReadKey();

編譯運行結果如下:
運行結果

4.基於上下文查詢元素
在一些應用中,需要根據元素上下狀態進行查詢。LINQ to XML類提供了以下兩個方法來獲取元素前後的兄弟元素
1.ElementsAfterSelf():獲取符合指定名稱,並按文檔順序和當前元素後面的同級元素的集合,返回類型爲IEnumerable
2.ElementsBeforeSelf():獲取符合指定名稱,並按文檔順序和當前元素前面的統計元素集合,返回類型爲:IEnumerable

在程序中添加如下方法進行上下查詢

//基於上下文進行查詢
static void QueryInContext()
{
    XElement root = XElement.Load(@"D:\UserList.xml");
    IEnumerable<XElement> users = root.Elements("User");
    //所有後續元素結點數量大於2的元素
    var query1 =
        from ele in users
        where ele.ElementsAfterSelf("User").Count() > 2
        select ele;
    Console.WriteLine("查詢結果:");
    foreach (var item in query1)
    {
        Console.WriteLine(item);
    }
    //所有前續元素結點數量大於2的元素
    var query2 =
       from ele in users
       where ele.ElementsBeforeSelf("User").Count() > 2
       select ele;
    Console.WriteLine("查詢結果:");
    foreach (var item in query2)
    {
        Console.WriteLine(item);
    }
}

在Main方法中添加如下代碼進行調用測試

QueryInContext();
Console.ReadKey();

編譯運行結果如下:
運行結果

  • 操作XML樹

1.加載和保存xml樹
加載xml樹到內存中的方法
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);
參數說明:
uri:string類型,表示要包含xml數據的文件路徑,這個路徑可以是相對路徑或絕對路徑。
textReader,reader:表示包含xml數據的文本數據流或xml數據流
options:LoadOptions枚舉類型,用來指定空白行爲及是否加載基URI和行信息
LoadOptions枚舉可選值:
None:不保留無關緊要的空白,也不加載基URI和行信息
PreserveWhiteSpace:分析時保留無關緊要的空白
SetBaseUri:從XmlReader請求基URI信息,並通過BaseUri屬性使此信息可用
SetLineInfo:從XmlReader請求行信息並通過XObject上的屬性使此信息可用

在程序中新增一個方法加載xml文件並讀取行信息

//操作xml樹
static void LoadXMLTree()
{
    //創建段簡單的xml數據
    string xmlData =
        @"<ItemList>
            <Item1 />
            <Item3 />
            <ITem5 />
           </ItemList>";
    //把xml數據寫入到臨進文件中
    File.WriteAllText("tempData.xml", xmlData);
    //使用Load方法來加載xml臨時文件中的內容,同時加載行和空白信息
    XElement ele = XElement.Load("tempData.xml", LoadOptions.SetLineInfo);
    //在Item1和Item3分別添加Item2,Item4兩個新的子元素
    ele.Element("Item1").AddAfterSelf(new XElement("Item2"));
    ele.Element("Item3").AddAfterSelf(new XElement("Item4"));
    //打印ele中所有元素,DescendantsAndSelf()這個方法是返回元素的集合
    foreach (XElement item in ele.DescendantsAndSelf())
    {
        //把XElement強制轉爲IXmlLineInfo類,從而可以獲取包含行號信息
        if (((IXmlLineInfo)item).HasLineInfo())
            Console.Write("Line {0} :\t", ((IXmlLineInfo)item).LineNumber);
        else
            Console.Write("Line XX:\t");
        Console.Write(item.Name);
        Console.WriteLine();
    }
}

在Main方法中調用這個方法:

LoadXMLTree();
Console.ReadKey();

編譯運行的結果如下:
運行結果
temList、Item1、Item3 和 Item5 都是從文件讀取,並且包含行信息,但是 Item2 和 Item4 則在加載之後新增,並不包含特定的行信息。並且我們可以看到新增記錄後,原有行信息仍是保持不變的。

2.向xml樹中添加元素
XElement類繼承自己XNode類和XContainer類,它們爲XElement類提供了幾種添加元素、屬性等節點的方法
a.Add():這個方法由XContainer類實現,在當前節點子節點的末尾添加內容
public void Add(Object content)
public void Add(params Object[] content)
b.AddFirst():這個方法由XContainer類實現,在當前節點的第一個子節點之前添加內容
public void AddFirst(Object content)
public void AddFirst(params Object[] content)
c.AddAfterSelf():這個方法由XNode類實現,在當前節點後面添加內容
public void AddAfterSelf(Object content)
public void AddAfterSelf(params Object[] content)
d.AddBeforeSelf():這個方法由XNode類實現,在當前節點前面添加內容
public void AddBeforeSelf(Object content)
public void AddBeforeSelf(params Obejct[] content)

從上面的定義可以看到,可以同時添加一個或多個xml元素,因而可以把LINQ查詢產生的IEnumerable類型的查詢結果直接通過上面的方法添加到XElement中,也可以把自己行創建的XElement數組或單個XElement對象添加到XElement中

3.移除xml樹中元素和屬性
XElement類本身提供的方法可以移除它的元素和屬性
RemoveAll()
RemoveAttributes()
這兩個方法不接受任何參數,也不返回任何值
RemoveAll():移除XElement中所有的元素和屬性
RemoveAttributes():移除XElement中所有的屬性

當只需要移除XElement元素的一個或多個屬性和子元素而並非全部時,可以使用另外的兩個方法
SetAttributeValue()和SetElementValue()
SetAttributeValue():用於設置XElement元素中指定屬性的值,當設置的值爲null時,表示刪除這個屬性
SetElementValue()用於設置XElement元素中指定子元素的值,當設置爲null時,表示刪除這個子元素
這兩個函數的具體定義如下:
public void SetAttributeValue(XName name,Object value)
public void SetElementValue(XName name,Object value)
name:表示要設置的屬性或子元素的名稱
value:表示要設置的新值

在程序中添加刪除元素和屬性的方法:

//xml元素和屬性刪除
static void RemoveElementAttribute()
{
    //原始數據的構建
    XElement ele = new XElement("Student");
    ele.SetAttributeValue("Name", "李四");
    ele.SetAttributeValue("Class", "181班");
    ele.SetAttributeValue("Age", 20);
    ele.SetElementValue("數學", 90);
    ele.SetElementValue("語文",80);
    ele.SetElementValue("英文", 70);
    ele.SetElementValue("綜合", 85);
    Console.WriteLine("原始數據:");
    Console.WriteLine(ele);

    //返回成績大於80分的元素
    IEnumerable<XElement> eleList =
        from e in ele.Elements()
        where int.Parse(e.Value) > 80
        select e;
    //移除查詢出的結果
    eleList.Remove();
    Console.WriteLine("移除成績大於80的元素後:");
    Console.WriteLine(ele);
    //獲取名稱爲"英文"的子元素,並做移除
    XElement eleEnglish = ele.Element("英文");
    eleEnglish.Remove();
    Console.WriteLine("再移除英文成績後:");
    Console.WriteLine(ele);

    //獲取名稱爲Age和Class的屬性,並移除屬性
    IEnumerable<XAttribute> atrList =
        from a in ele.Attributes()
        where (a.Name == "Class") || (a.Name == "Age")
        select a;
    atrList.Remove();
    Console.WriteLine("再移除Age和Class屬性後:");
    Console.WriteLine(ele);
}

在Main方法中對這個方法做調用測試

RemoveElementAttribute();
Console.ReadKey();

編譯運行結果如下:
運行結果

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章