程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#中的Linq to Xml詳解

C#中的Linq to Xml詳解

編輯:C#入門知識

C#中的Linq to Xml詳解。本站提示廣大學習愛好者:(C#中的Linq to Xml詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是C#中的Linq to Xml詳解正文


媒介

我信任許多從事.NET開辟的,在.NET 3.5之前操作XML會比擬費事,然則在此以後湧現了Linq to Xml,而明天的主人公就是Linq to Xml,空話不多說,直接進入主題。

1、生成Xml

為了可以或許在構造有必定的組織,筆者建議年夜家新建一個掌握台項目,而且新建一個CreateXml類(以下部門都屬於該類中)。

並在個中寫入以部屬性:

public static String Path
        {
            get
            {
                String path = String.Format("{0}\\test.xml", Environment.CurrentDirectory);
                return path;
            }
        }

這句代碼很好懂得,就是為了上面我們示例的時刻可以將xml保留到以後法式的運轉途徑下。

(以下的示例中不會包括Main辦法中的寫法,由於Main中僅僅只需挪用該靜態辦法便可。)

1.創立簡略的Xml

起首我們先練練手,創立一個簡略的Xml並保留到一個文件中。

代碼以下:

/// <summary>
/// 創立簡略的xml並保留
/// </summary>
public static void CreateElement()
{
XDocument xdoc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("root",
new XElement("item", "1"),
new XElement("item", "2")
));
xdoc.Save(Path);
}

許多進修過XML的人可以從構造就可以夠猜想出終究的xml的組織,而這也是linq to xml的長處之一。這句代碼起首創立一個xml文檔,並設置該xml的版本為1.0,

采取utf-8編碼,前面的yes表現該xml是自力的。上面就開端創立每一個節點的,起首是Root節點,然後在Root節點中添加兩個Item節點。

終究生成的Xml以下所示:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<root>
    <item>1</item>
    <item>2</item>
</root>

2.創立正文

當xml有許多項時,我們就須要應用正文加以差別,經由過程linq to xml我們一樣可以在個中添加正文。

好比上面這段代碼:

/// <summary>
        /// 創立正文
        /// </summary>
        public static void CreateComment()
        {
            XDocument doc = new XDocument(
                new XDeclaration("1.0", "utf-8", "yes"),
                new XComment("提醒"),
                new XElement("item", "asd")
                );
            doc.Save(Path);
        }

這裡我們直接在版本信息的前面添加了一條正文。

終究的成果以下所示:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!--提醒-->
<item>asd</item>

3.依據對象創立xml

許多時刻我們都邑將數組之類的類型轉換成xml以便保留進永遠性存儲介質中,所以上面我們也簡略的舉了一個例子,將數組轉換成xml。

代碼以下所示:

/// <summary>
        /// 依據對象創立xml並保留
        /// </summary>
        public static void CreateElementByObjects()
        {
            var s = Enumerable.Range(1, 10);
            XElement xele = new XElement(
                "Root",
                from item in s
                select new XElement("item", item.ToString())
                );
            xele.Save(Path);
        }

一開端的代碼 var s = Enumerable.Radge(1,10)是從1開端遞增,生成含有10項的數組,以便前面我們停止添加,有了這個數組以後,

我們經由過程簡略的linq語句將數組轉換成xml,添加到Root中。

保留以後的成果以下:

<?xml version="1.0" encoding="utf-8"?>
<Root>
  <item>1</item>
  <item>2</item>
  <item>3</item>
  <item>4</item>
  <item>5</item>
  <item>6</item>
  <item>7</item>
  <item>8</item>
  <item>9</item>
  <item>10</item>
</Root>

4.創立屬性

有時我們不想創立新的子項去保留數據,而是應用屬性的方法去保留。理所應該,linq to xml一樣也支撐這個功效,上面我們可以經由過程簡略的語句去完成它。

代碼以下所示:

/// <summary>
        /// 創立屬性
        /// </summary>
        public static void CreteAttribute()
        {
            XAttribute xa = new XAttribute("V2", "2");
            XElement xele = new XElement(
                "Root",
                new XElement("Item",
                    new XAttribute("V1", "1"),
                    xa
                    ));
            xele.Save(Path);
        }

我們仍然可以看到熟習的語法,這裡我們應用了XAttribute去創立一個屬性,並添加到XElement中。

終究的成果以下:

<?xml version="1.0" encoding="utf-8"?>
<Root>
  <Item V1="1" V2="2" />
</Root>

5.創立定名空間

關於一些企業級的xml格局,會異常的嚴厲。特殊是在統一個xml中能夠會湧現反復的項,然則我們又想辨別開來,這個時刻我們可以應用定名空間將他們離開(跟C#中的定名空間相似。)。

上面是創立定名空間的示例:

/// <summary>
        /// 創立定名空間
        /// </summary>
        public static void CreateNamespace()
        {
            XElement xele = new XElement("{http://www.xamarin-cn.com}Root",
                new XElement("Item", "1"),
                new XElement("{http://www.百度.com}Item", 2));
            xele.Save(Path);
        }

成果以下所示:

<?xml version="1.0" encoding="utf-8"?>
<Root xmlns="http://www.xamarin-cn.com">
  <Item xmlns="">1</Item>
  <Item xmlns="http://www.百度.com">2</Item>
</Root>

從這個成果中我們可以看到對應的屬性中有了xmlns屬性,而且值就是我們賦給它的定名空間。

2、查詢並修正Xml

Linq to xml不只僅是創立xml簡略,在查詢,編纂和刪除方面一樣長短常便利的。上面我們就會引見這些。

起首我們創立一個QueryXml類,並在個中寫入以下的屬性:

public static String Path
        {
            get
            {
                String path = String.Format("{0}\\test1.xml", Environment.CurrentDirectory);
                return path;
            }
        }

同時在該途徑下新建一個test1.xml文件,並在個中寫入以下內容:

<?xml version="1.0" encoding="utf-8"?>
<Root>
   <Item v1="1" v2="2">Item1</Item>
   <Item v1="1" v2="2" >Item2</Item>
</Root>

 
上面我們便可以正式開端了。

1.經由過程文件讀取xml

既然我們要對xml查詢就須要讀取對應的xml文件,固然前面會引見其他的方法。

代碼以下:

/// <summary>
        /// 經由過程文件讀取xml
        /// </summary>
        public static void QueryElementByFile()
        {
            XElement xele = XElement.Load(Path);
            XElement xele1 = xele.Element("Item");
            Console.Write(xele1.Value.Trim());
            Console.ReadKey();
        }

我們可以應用XElement的靜態辦法Load讀取指定途徑下的xml文件,這裡我們不只讀取了該xml文件,同時還獲得的該xml的第一個item的值並輸入。

所以我們可以看到以下的成果:

2.在指定節點前後添加新節點

下面我們僅僅只是讀取xml和簡略的查詢,上面我們不只僅查詢而且還要在該節點前後拔出新的節點。

代碼以下:

/// <summary>
        /// 在指定節點前後添加新節點
        /// </summary>
        public static void AddToElementAfterAndBefore()
        {
            XElement xele = XElement.Load(Path);
            var item = (from ele in xele.Elements("Item")
                        where ele.Value.Equals("Item2")
                        select ele).SingleOrDefault();
            if (item != null)
            {
                XElement nele = new XElement("NItem", "NItem");
                XElement nele2 = new XElement("BItem", "BItem");
                item.AddAfterSelf(nele);
                item.AddBeforeSelf(nele2);
                xele.Save(Path);
            }
        }

我們簡略的剖析一下下面的代碼,起首我們應用linq從中查詢Item的值為Item2的節點,然後獲得個中第一個節點,然後經由過程AddAfterSelf和AddBeforeSelf在該節點的前面和後面分離添加新的節點。

添加完以後的xml成果以下:


<?xml version="1.0" encoding="utf-8"?>
<Root>
  <Item v1="1" v2="2">Item1</Item>
  <BItem>BItem</BItem>
  <Item v1="1" v2="2">Item2</Item>
  <NItem>NItem</NItem>
</Root>

3.添加屬性到節點中

我們曾經可以靜態的添加節點,然則創立的時刻不只僅可以創立節點,而且還能創立屬性,上面我們可以經由過程SetAttributeValue去添加新的屬性或許修正現有屬性。

代碼以下:

/// <summary>
        /// 添加屬性到節點中
        /// </summary>
        public static void AddAttributeToEle()
        {
            XElement xele = XElement.Parse(@"<?xml version='1.0' encoding='utf-8'?><Root><!--後面的正文-->
<Item v1='1' v2='2'>Item1</Item><!--前面的正文--><Item v1='1' v2='2' v3='3'>Item2</Item></Root>");
            var item = (from ele in xele.Elements("Item")
                        where ele.Value.Equals("Item2")
                        select ele).SingleOrDefault();
            item.SetAttributeValue("v3", "3");
            xele.Save(Path);
        }

我們可以顯著的看出,這裡我們曾經不是應用XElement.Load去讀取xml文件,而是經由過程直接讀取xml字符串。接著我們照樣跟下面一樣去查詢,然後經由過程SetAttributeValue添加了新的屬性,並保留。

Xml內容以下:

<?xml version="1.0" encoding="utf-8"?>
<Root>
  <!--後面的正文-->
  <Item v1="1" v2="2">Item1</Item>
  <!--前面的正文-->
  <Item v1="1" v2="2" v3="3">Item2</Item>
</Root>

我們可以看到第二個Item中多了一個 v3=”3” 新的屬性。

4.添加正文到指定節點前後

這裡的語法根本跟添加節點到指定節點前後是類似的,只是讀取xml的方法分歧。

代碼以下:

/// <summary>
        /// 添加正文到節點前後
        /// </summary>
        public static void AddCommentToAfterAndBefore()
        {
            TextReader tr = new StringReader(@"<?xml version='1.0' encoding='utf-8'?><Root><!--後面的正文-->
<Item v1='1' v2='2'>Item1</Item><!--前面的正文--><Item v1='1' v2='2' v3='3'>Item2</Item></Root>");
            XElement xele = XElement.Load(tr);
            var item = (from ele in xele.Elements("Item")
                        where ele.Value.Equals("Item1")
                        select ele).FirstOrDefault();
            if (item != null)
            {
                XComment xcom = new XComment("前面的正文");
                XComment xcoma = new XComment("後面的正文");
                item.AddAfterSelf(xcom);
                item.AddBeforeSelf(xcoma);
            }
            tr.Close();
            xele.Save(Path);
        }

下面我應用StringReader和TextReader讀取xml字符串並應用XElement.Load讀取該對象,然後就是在新建節點的時刻新建的是正文節點,最初應用一樣的語法添加到指定節點前後。

終究成果以下:

<?xml version="1.0" encoding="utf-8"?>
<Root>
  <!--後面的正文-->
  <!--後面的正文-->
  <Item v1="1" v2="2">Item1</Item>
  <!--前面的正文-->
  <!--前面的正文-->
  <Item v1="1" v2="2" v3="3">Item2</Item>
</Root>

5.調換指定節點

修正節點的值經由過程SetValue便可做到,然則有時觸及到子節點,而我們想一次性全體調換失落,那末我們就須要應用WordStrWith。

代碼以下:

/// <summary>
        /// 調換指定節點
        /// </summary>
        public static void WordStrElement()
        {
            XElement xele = XElement.Load(Path);
            var item = (from ele in xele.Elements("Item")
                        where ele.Value.Equals("Item2")
                        select ele).FirstOrDefault();
            if (item != null)
            {
                item.WordStrWith(new XElement("Item", "Item3"));
            }
            xele.Save(Path);
        }

這裡的重點在於WordStrWith辦法,挪用該辦法會產生兩個操作。起首是刪除該節點,然後在該節點的地位大將我們的節點拔出完成調換。

最初的xml成果以下:


<?xml version="1.0" encoding="utf-8"?>
<Root>
  <!--後面的正文-->
  <!--後面的正文-->
  <Item v1="1" v2="2">Item1</Item>
  <!--前面的正文-->
  <!--前面的正文-->
  <Item>Item3</Item>
</Root>

如許我們很隨意馬虎的就調換了全部節點。

6.刪除指定屬性

後面我們引見了創立、修正和添加屬性,然則還沒有引見若何刪除指定的屬性,上面我們就經由過程一個簡略的實例來演示。

代碼以下:

/// <summary>
        /// 刪除指定屬性
        /// </summary>
        public static void RemoveAttribute()
        {
            XElement xele = XElement.Load(Path);
            var item = (from ele in xele.Elements("Item")
                        where ele.Value.Equals("Item1")
                        select ele).FirstOrDefault().Attribute("v1");
            if (item != null)
            {
                item.Remove();
            }
            xele.Save(Path);
        }

我們起首查詢出指定的節點,然後指定某個屬性,最初挪用XAttribute的Remove辦法既可。

成果以下:

<?xml version="1.0" encoding="utf-8"?>
<Root>
  <!--後面的正文-->
  <!--後面的正文-->
  <Item v2="2">Item1</Item>
  <!--前面的正文-->
  <!--前面的正文-->
  <Item>Item3</Item>
</Root>

7.刪除指定節點

既然下面曾經可以刪除屬性,天然也少不了刪除屬性。

代碼以下所示:

/// <summary>
        /// 刪除指定節點
        /// </summary>
        public static void RemoveElement()
        {
            XElement xele = XElement.Load(Path);
            var item = (from ele in xele.Elements("Item")
                        where ele.Value.Equals("Item1")
                        select ele).FirstOrDefault();
            if (item != null)
            {
                item.Remove();
            }
            xele.Save(Path);
        }

仍然是挪用異樣的辦法。

成果以下:

<?xml version="1.0" encoding="utf-8"?>
<Root>
  <!--後面的正文-->
  <!--後面的正文-->
  <!--前面的正文-->
  <!--前面的正文-->
  <Item>Item3</Item>
</Root>

3、按節點關系查詢

下面的查詢都是經由過程相干的前提停止查詢,然則我們有時僅僅只須要經由過程之間的關系便可,如許反而可以免許多的代碼,固然略加摸索可以發明其實XElement都供給給我們了。

我們仍然要新建一個StructureXml類,並在個中新建一個屬性。

以下所示:

public static String Path
        {
            get
            {
                String path = String.Format("{0}\\test2.xml", Environment.CurrentDirectory);
                return path;
            }
        }

同時在該文件夾下新建一個test2.xml並寫入以下內容:


<?xml version="1.0" encoding="utf-8" ?>
<Root>
  <Item>
    <SubItem1>
      1
    </SubItem1>
    <SubItem>
      <Child>
        sss
      </Child>
    </SubItem>
    <SubItem2>
      2
    </SubItem2>
  </Item>
</Root>

1.顯示指定節點的一切父節點

經由過程下面的xml文件,我們清楚的看出xml是具有構造性的,彼此之間都存在關系,而如今我們須要顯示某個節點的父級節點的稱號。

代碼以下所示:

/// <summary>
        /// 顯示指定節點的一切父節點
        /// </summary>
        public static void ShowAllParentEle()
        {
            XElement xele = XElement.Load(Path);
            var item = (from ele in xele.Descendants("Child")
                        select ele).FirstOrDefault();
            if (item != null)
            {
                foreach (var sub in item.Ancestors())
                {
                    Console.WriteLine(sub.Name);
                }
                Console.WriteLine("----------------");
                foreach (var sub in item.AncestorsAndSelf())
                {
                    Console.WriteLine(sub.Name);
                }
                Console.ReadKey();
            }
        }

個中我們經由過程Descendants獲得最底的節點,然後應用Ancestors獲得一切的父級節點,而AncestorsAndSelf則表現包括自己。

終究成果以下所示:

我們從圖中看出,朋分線前顯示的是不包括自己的,而上面是包括自己的。

2.顯示指定節點的一切子節點

我們不只僅可以輸入一個節點的一切父級節點,異樣也能夠輸入一個節點的一切子節點。

代碼以下所示:


/// <summary>
        /// 顯示指定節點的一切子節點
        /// </summary>
        public static void ShowAllChildEle()
        {
            XElement xele = XElement.Load(Path);
            foreach (var sub in xele.Descendants())
            {
                Console.WriteLine(sub.Name);
            }
            Console.WriteLine("-----------------");
            foreach (var sub in xele.DescendantsAndSelf())
            {
                Console.WriteLine(sub.Name);
            }
            Console.ReadKey();
        }

這裡我們仍然是分紅輸入子級節點和包括本身的。

成果以下所示:

3.顯示同級節點之前的節點

既然有了父子關系,固然也少不了同級關系,起首我們先顯示同級節點之前的節點。

代碼以下所示:

/// <summary>
        /// 顯示同級節點之前的節點
        /// </summary>
        public static void ShowPrevEle()
        {
            XElement xele = XElement.Load(Path);
            var item = (from ele in xele.Descendants("SubItem")
                        select ele).FirstOrDefault();
            if (item != null)
            {
                foreach (var sub in item.ElementsBeforeSelf())
                {
                    Console.WriteLine(sub.Name);
                }
            }
            Console.ReadKey();
        }

這裡我們看到我們經由過程ElementsBeforeSelf獲得該節點之前的同級節點,固然我們還可以傳入參數作為限制前提。這裡我們經由過程查詢獲得了SubItem這個節點,並顯示該節點之前的同級節點。

終究成果以下:

4.顯示同級節點前面的節點

作為下面的彌補。

代碼以下所示:

/// <summary>
        /// 顯示同級節點前面的節點
        /// </summary>
        public static void ShowNextEle()
        {
            XElement xele = XElement.Load(Path);
            var item = (from ele in xele.Descendants("SubItem")
                        select ele).FirstOrDefault();
            if (item != null)
            {
                foreach (var sub in item.ElementsAfterSelf())
                {
                    Console.WriteLine(sub.Name);
                }
            }
            Console.ReadKey();
        }

終究成果以下所示:

4、監聽xml事宜

你能夠會困惑xml為何還要監聽,其實如許是成心義的,好比你要依據某個節點的值作為依附,那末你就要監聽這個節點,假如這個節點產生轉變的時刻,

你才可和時的作出反響。然則xml的事宜監聽有一個特色,跟閱讀器中的DOM事宜相似,監聽父節點異樣也能夠監聽的到它的子節點的事宜。上面我們

經由過程一個簡略的實例來講明。

實例代碼以下:

public static class EventXml
    {
        public static void BindChangeing()
        {
            XElement xele = new XElement("Root");
            xele.Changing += xele_Changing;
            xele.Changed += xele_Changed;
            xele.Add(new XElement("Item", "123"));
            var item = xele.Element("Item");
            item.WordStrWith(new XElement("Item", "2"));
            item = xele.Element("Item");
            item.Remove();
            Console.ReadKey();
        }

        static void xele_Changed(object sender, XObjectChangeEventArgs e)
        {
            XElement ele = sender as XElement;
            Console.WriteLine(String.Format("已完成 {0}-{1}", ele.Name, e.ObjectChange));
        }

        static void xele_Changing(object sender, XObjectChangeEventArgs e)
        {
            XElement ele = sender as XElement;
            Console.WriteLine(String.Format("正在停止中 {0}-{1}", ele.Name, e.ObjectChange));
        }
}


個中的症結就是Changing和Changed事宜,其次就是在事宜中斷定事宜的起源。

終究成果以下所示:

5、處置xml流

在現實的貿易化的開辟中,xml弗成能僅僅保留這麼點數據。有能夠保留著異常多的數據。然則我們照樣依照以往的方法,就會將xml全體讀取進內存。

如許會占領許多內存,影響體系的機能,針對這類情形我們須要應用流的方法行止理xml,由於流會依照我們的次序讀取部門xml進內存,其實不會將所

有xml都讀取進內存。

Xml文件內容以下所示:

<?xml version="1.0" encoding="utf-8" ?>
<Root>
  <SubItem>1</SubItem>
  <SubItem>1</SubItem>
  <SubItem>1</SubItem>
  <Item>A</Item>
  <SubItem>1</SubItem>
  <Item>B</Item>
</Root>

代碼以下所示:

public static class ReadXmlStream
    {
        public static String Path
        {
            get
            {
                String path = String.Format("{0}\\test3.xml", Environment.CurrentDirectory);
                return path;
            }
        }

        /// <summary>
        /// 流式處置XML
        /// </summary>
        public static void ReadXml()
        {
            XmlReader reader = XmlReader.Create(Path);
            while (reader.Read())
            {
                if (reader.NodeType == XmlNodeType.Element && reader.Name.Equals("Item"))
                {
                    XElement ele = XElement.ReadFrom(reader) as XElement;
                    Console.WriteLine(ele.Value.Trim());
                }
            }
            Console.ReadKey();
        }
}

這裡我們經由過程XmlReader的Create靜態辦法翻開xml文件,並經由過程Read一個節點的停止讀取,並斷定該節點的類型。

終究成果以下:

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved