C#讀寫XML文件方法整理

一.前言:
XML是微軟.Net戰略的一個重要組成部分,而且它可謂是XML Web服務的基石,所以掌握.Net框架下的XML技術自然顯得非常重要了。本文將指導大家如何運用C#語言完成.Net框架下的XML文檔的讀寫操作。首先,我會向大家介紹.Net框架中與XML相關的命名空間和其中的重要類。其次,我還會給出有關的實例以使讀者更進一步的瞭解XML文檔的讀寫操作的具體方法。

二.XML命名空間和相關類簡介:

在深入進行.Net框架下的XML文檔的操作之前,我想很有必要向大家介紹.Net框架中與XML技術有關的命名空間和其中一些重要的類。.Net框架爲我們提供了以下一些命名空間:System.Xml、System.Xml.Schema、 System.Xml.Serialization、System.Xml.Xpath以及 System.Xml.Xsl來包容和XML操作相關的類。

System.Xml命名空間包含了一些最重要的XML類,其中最主要的類是和XML文檔的讀寫操作相關的類。這些類中包括4個與讀相關的類以及2個與寫相關的類。它們分別是:XmlReader、XmlTextReader、 XmlValidatingReader、XmlNodeReader、XmlWriter以及 XmlTextWriter。本文將重點介紹這些類,因爲它們是最基本也是最重要的類。

XmlReader類是一個虛基類,它包含了讀XML文檔的方法和屬性。該類中的Read方法是一個基本的讀XML文檔的方法,它以流形式讀取XML文檔中的節點(Node)。另外,該類還提供了ReadString、ReadInnerXml、 ReadOuterXml和ReadStartElement等更高級的讀方法。除了提供讀XML文檔的方法外,XmlReader類還爲程序員提供了 MoveToAttribute、MoveToFirstAttribute、MoveToContent、MoveToFirstContent、 MoveToElement以及 MoveToNextAttribute等具有導航功能的方法。在本文後面介紹的實例中,我們將運用到這些方法。

XmlTextReader、XmlNodeReader以及XmlValidatingReader等類是從XmlReader類繼承過來的子類。根據它們的名稱,我們可以知道其作用分別是讀取文本內容、讀取節點和讀取XML模式(Schemas)。

XmlWriter類爲程序員提供了許多寫XML文檔的方法,它是XmlTextWriter類的基類,我在後面的實例中會給出相關的運用方法。

XmlNode類是一個非常重要的類,它代表了XML文檔中的某個節點。該節點可以是XML文檔的根節點,這樣它就代表整個XML文檔了。它是許多很有用的類的基類,這些類包括插入節點的類、刪除節點的類、替換節點的類以及在XML文檔中完成導航功能的類。同時,XmlNode類還爲程序員提供了獲取雙親節點、子節點、最後一個子節點、節點名稱以及節點類型等的屬性。它的三個最主要的子類包括: XmlDocument、XmlDataDocument以及XmlDocumentFragment。XmlDocument類代表了一個XML文檔,它提供了載入和保存XML文檔的方法和屬性。這些方法包括了Load、LoadXml和Save等。同時,它還提供了添加特性(Attributes)、說明(Comments)、空間(Spaces)、元素(Elements)和新節點(New Nodes)等XML項的功能。XmlDocumentFragment類代表了一部分XML文檔,它能被用來添加到其他的XML文檔中。 XmlDataDocument類可以讓程序員更好地完成和ADO.NET中的數據集對象之間的互操作。

除了上面介紹的System.Xml命名空間中的類外,該命名空間還包括了XmlConvert、XmlLinkedNode以及XmlNodeList等類,不過這些類不是本文介紹的重點,有興趣的讀者不妨去參考相關文檔資料。

System.Xml.Schema命名空間中包含了和XML模式相關的類,這些類包括XmlSchema、XmlSchemaAll、XmlSchemaXPath以及XmlSchemaType等類。

System.Xml.Serialization命名空間中包含了和XML文檔的序列化和反序列化操作相關的類,XML文檔的序列化操作能將XML格式的數據轉化爲流格式的數據並能在網絡中傳輸,而反序列化則完成相反的操作,即將流格式的數據還原成XML格式的數據。

System.Xml.XPath命名空間包含了XPathDocument、 XPathExression、XPathNavigator以及XPathNodeIterator等類,這些類能完成XML文檔的導航功能。在 XPathDocument類的協助下,XPathNavigator類能完成快速的XML文檔導航功能,該類爲程序員提供了許多Move方法以完成導航功能。

System.Xml.Xsl命名空間中的類完成了XSLT的轉換功能。

三.讀XML文檔的方法:

在介紹完.Net框架中和XML有關的命名空間和相關類後,我接着向大家介紹和XML相關的一些操作。首先,我向大家介紹的讀取XML文檔的方法。在下面的實例程序中,我將運用VS.net開發工具附帶的"books.xml"文件來作爲示例。你可以在你的機器上搜索到該文件(或請參考附錄),或者你也可以運用其他的XML文件。

首先,我們用XmlTextReader類的對象來讀取該XML文檔。方法很簡單,就是在創建新對象的構造函數中指明XML文件的位置即可。

XmlTextReader textReader = new XmlTextReader("C://books.xml");

一旦新對象創建完畢,你就可以調用其Read方法來讀取XML文檔了。調用Read方法之後,信息被存儲起來,你可以通過讀取該對象的Name、BaseURI、Depth、LineNumber等屬性來獲取這些信息。下面我給出一個完整的實例,該實例通過簡單的讀取"books.xml"文件,然後將其中的信息顯示在控制檯中。

using System;
using System.Xml;

namespace ReadXml
{
    class Class1
    {
        static void Main( string[] args )
        {
            // 創建一個XmlTextReader類的對象並調用Read方法來讀取文件
            XmlTextReader textReader = new XmlTextReader("C://books.xml");
            textReader.Read();
            // 節點非空則執行循環體
            while ( textReader.Read() )
            {
                // 讀取第一個元素
                textReader.MoveToElement();
                Console.WriteLine("XmlTextReader Properties Test");
                Console.WriteLine("===================");

                // 讀取該元素的屬性並顯示在控制檯中
                Console.WriteLine("Name:" + textReader.Name);
                Console.WriteLine("Base URI:" + textReader.BaseURI);
                Console.WriteLine("Local Name:" + textReader.LocalName);
                Console.WriteLine("Attribute Count:" + textReader.AttributeCount.ToString());
                Console.WriteLine("Depth:" + textReader.Depth.ToString());
                Console.WriteLine("Line Number:" + textReader.LineNumber.ToString());
                Console.WriteLine("Node Type:" + textReader.NodeType.ToString());
                Console.WriteLine("Attribute Count:" + textReader.Value.ToString());
            }
        }
    }
}

 

XmlTextReader類中有一個很重要的屬性-NodeType,通過該屬性,我們可以知道其節點的節點類型。而枚舉類型XmlNodeType中包含了諸如Attribute、CDATA、Element、Comment、 Document、DocumentType、Entity、ProcessInstruction以及WhiteSpace等的XML項的類型。通過與 XmlNodeType中的元素的比較,我們可以獲取相應節點的節點類型並對其完成相關的操作。下面我就給出一個實例,該實例讀取每個節點的 NodeType,並根據其節點類型顯示其中的內容,同時程序還記錄了XML文件中每種節點類型的數目。

using System;
using System.Xml;

namespace ReadXML
{
    class Class2
    {
        static void Main( string[] args )
        {
            int ws = 0;
            int pi = 0;
            int dc = 0;
            int cc = 0;
            int ac = 0;
            int et = 0;
            int el = 0;
            int xd = 0;

            XmlTextReader textReader = new XmlTextReader("C://books.xml");

            while (textReader.Read())
            {
                XmlNodeType nType = textReader.NodeType;

                // 節點類型爲XmlDeclaration
                if (nType == XmlNodeType.XmlDeclaration)
                {
                    Console.WriteLine("Declaration:" + textReader.Name.ToString());
                    xd = xd + 1;
                }          

                // 節點類型爲Comment
                if( nType == XmlNodeType.Comment)
                {
                    Console.WriteLine("Comment:" + textReader.Name.ToString());
                    cc = cc + 1;
                }          

                // 節點類型爲Attribute
                if( nType == XmlNodeType.Attribute)
                {
                    Console.WriteLine("Attribute:" + textReader.Name.ToString());
                    ac = ac + 1;
                }

                // 節點類型爲Element
                if ( nType == XmlNodeType.Element)
                {
                    Console.WriteLine("Element:" + textReader.Name.ToString());
                    el = el + 1;
                }

                // 節點類型爲Entity
                if ( nType == XmlNodeType.Entity )
                {
                    Console.WriteLine("Entity:" + textReader.Name.ToString());
                    et = et + 1;
                }          

                // 節點類型爲Process Instruction
                if( nType == XmlNodeType.ProcessingInstruction )
                {
                    Console.WriteLine("Process Instruction:" + textReader.Name.ToString());
                    pi = pi + 1;
                }      

                // 節點類型爲DocumentType
                if( nType == XmlNodeType.DocumentType)
                {
                    Console.WriteLine("DocumentType:" + textReader.Name.ToString());
                    dc = dc + 1;
                }

                // 節點類型爲Whitespace
                if ( nType == XmlNodeType.Whitespace )
                {
                    Console.WriteLine("WhiteSpace:" + textReader.Name.ToString());
                    ws = ws + 1;
                }
            }

            // 在控制檯中顯示每種類型的數目
            Console.WriteLine("Total Comments:" + cc.ToString());
            Console.WriteLine("Total Attributes:" + ac.ToString());
            Console.WriteLine("Total Elements:" + el.ToString());
            Console.WriteLine("Total Entity:" + et.ToString());
            Console.WriteLine("Total Process Instructions:" + pi.ToString());
            Console.WriteLine("Total Declaration:" + xd.ToString());
            Console.WriteLine("Total DocumentType:" + dc.ToString());
            Console.WriteLine("Total WhiteSpaces:" + ws.ToString());
        }
    }
}

 

以上,我向大家介紹瞭如何運用XmlTextReader類的對象來讀取XML文檔,並根據節點的NodeType屬性來取得其節點類型信息。同時XmlReader這個基類還有XmlNodeReader和 XmlValidatingReader等派生類,它們分別是用來讀取XML文檔的節點和模式的。限於篇幅,這裏就不介紹了,讀者可以參考有關資料。
四.寫XML文檔的方法:

XmlWriter類包含了寫XML文檔所需的方法和屬性,它是XmlTextWriter類和 XmlNodeWriter類的基類。該類包含了WriteNode、WriteString、WriteAttributes、 WriteStartElement以及WriteEndElement等一系列寫XML文檔的方法,其中有些方法是成對出現的。比如你要寫入一個元素,你首先得調用WriteStartElement方法,接着寫入實際內容,最後是調用WriteEndElement方法以表示結束。該類還包含了 WriteState、XmlLang和XmlSpace等屬性,其中WriteState屬性表明了寫的狀態。因爲XmlWriter類包含了很多寫 XML文檔的方法,所以這裏只是介紹最主要的幾種。下面我們通過其子類XmlTextWriter類來說明如何寫XML文檔。

首先,我們要創建一個XmlTextWriter類的實例對象。該類的構造函數 XmlTextWriter有三種重載形式,其參數分別爲一個字符串、一個流對象和一個TextWriter對象。這裏我們運用字符串的參數形式,該字符串就指明瞭所要創建的XML文件的位置,方法如下:

XmlTextWriter textWriter = New XmlTextWriter("C://myXmFile.xml", null);

 

在創建完對象後,我們調用WriterStartDocument方法開始寫XML文檔,在完成寫工作後,就調用WriteEndDocument結束寫過程並調用Close方法將它關閉。在寫的過程中,我們可以調用WriteComment方法來添加說明,通過調用WriteString方法來添加一個字符串,通過調用WriteStartElement和WriteEndElement方法對來添加一個元素,通過調用WriteStartAttribute和WriteEndAttribute方法對來添加一個屬性。我們還可以通過調用 WriteNode方法來添加整一個節點,其它的寫的方法還包括WriteProcessingInstruction和WriteDocType等等。下面的實例就是介紹如何具體運用這些方法來完成XML文檔的寫工作的。

using System;
using System.Xml;

namespace WriteXML
{
class Class1
{
   static void Main( string[] args )
   {
    try
    {
     // 創建XmlTextWriter類的實例對象
     XmlTextWriter textWriter = new XmlTextWriter("C://w3sky.xml", null);
     textWriter.Formatting = Formatting.Indented;

     // 開始寫過程,調用WriteStartDocument方法
     textWriter.WriteStartDocument();

     // 寫入說明
     textWriter.WriteComment("First Comment XmlTextWriter Sample Example");
     textWriter.WriteComment("w3sky.xml in root dir");  

     //創建一個節點
     textWriter.WriteStartElement("Administrator");
     textWriter.WriteElementString("Name", "formble");
     textWriter.WriteElementString("site", "w3sky.com");
     textWriter.WriteEndElement();
   


     // 寫文檔結束,調用WriteEndDocument方法
     textWriter.WriteEndDocument();

     // 關閉textWriter
     textWriter.Close();

    }
    catch(System.Exception e)
    {
     Console.WriteLine(e.ToString());
    }
   }
}
}

 


五.運用XmlDocument類:

XmlDocument類的對象代表了一個XML文檔,它也是一個非常重要的XML類。該類包含了 Load、LoadXml以及Save等重要的方法。其中Load方法可以從一個字符串指定的XML文件或是一個流對象、一個TextReader對象、一個XmlReader對象導入XML數據。LoadXml方法則完成從一個特定的XML文件導入XML數據的功能。它的Save方法則將XML數據保存到一個XML文件中或是一個流對象、一個TextWriter對象、一個XmlWriter對象中。

下面的程序中我們用到了XmlDocument類對象的LoadXml方法,它從一個XML文檔段中讀取XML數據並調用其Save方法將數據保存在一個文件中。

// 創建一個XmlDocument類的對象
XmlDocument doc = new XmlDocument();
doc.LoadXml(("<Student type='regular' Section='B'><Name>Tommy Lex</Name></Student>"));

// 保存到文件中
doc.Save("C://student.xml");

 

這裏,我們還可以通過改變Save方法中參數,將XML數據顯示在控制檯中,方法如下:

doc.Save(Console.Out);

至於文件的刪除工作,則可採用與刪除一般文件相同的方法:

System.IO.File.Delete( @"c:/abc.txt" );

或者:

Directory.Delete( "E:/SQLDB/MSSQL/Backup ",true); //刪除目錄及子文件

File.Create( "E:/SQLDB/MSSQL/Backup ")


補充:C#中如何刪除文件名以任意字母開頭的文件


而在下面的程序中,我們用到了一個XmlTextReader對象,通過它我們讀取 "books.xml"文件中的XML數據。然後創建一個XmlDocument對象並載入XmlTextReader對象,這樣XML數據就被讀到 XmlDocument對象中了。最後,通過該對象的Save方法將XML數據顯示在控制檯中。

XmlDocument doc = new XmlDocument();
// 創建一個XmlTextReader對象,讀取XML數據
XmlTextReader reader = new XmlTextReader("c://books.xml");
reader.Read();

// 載入XmlTextReader類的對象
doc.Load(reader);
// 將XML數據顯示在控制檯中
doc.Save(Console.Out);

六.總結:

XML技術作爲.Net的基石,其重要性自然不言而喻。.Net框架包含了五個命名空間和大量的類來支持與XML技術有關的操作。其中System.Xml是最重要的一個命名空間,其中的XmlReader類和XmlWriter類以及它們的派生類完成了 XML文檔的讀寫操作,是最基本也是最重要的類。XmlDocument類代表了XML文檔,它能完成與整個XML文檔相關的各類操作,同時和其相關的 XmlDataDocument類也是非常重要的,值得讀者的深入研究。

附錄

"books.xml"文件如下:

<?xml version='1.0'?>
<!-- This file represents a fragment of a book store inventory database -->
<bookstore>
<book genre="autobiography" publicationdate="1981" ISBN="1-861003-11-0">
    <title>The Autobiography of Benjamin Franklin</title>
    <author>
      <first-name>Benjamin</first-name>
      <last-name>Franklin</last-name>
    </author>
    <price>8.99</price>
</book>
<book genre="novel" publicationdate="1967" ISBN="0-201-63361-2">
    <title>The Confidence Man</title>
    <author>
      <first-name>Herman</first-name>
      <last-name>Melville</last-name>
    </author>
    <price>11.99</price>
</book>
<book genre="philosophy" publicationdate="1991" ISBN="1-861001-57-6">
    <title>The Gorgias</title>
    <author>
      <first-name>Sidas</first-name>
      <last-name>Plato</last-name>
    </author>
    <price>9.99</price>
</book>
</bookstore>

 

#########################################################################

 

已知有一個XML文件(bookstore.xml)如下:
<?xml version="1.0" encoding="gb2312"?>
<bookstore>
  <book genre="fantasy" ISBN="2-3631-4">
    <title>Oberon's Legacy</title>
    <author>Corets, Eva</author>
    <price>5.95</price>
  </book>
</bookstore>
 
1、往<bookstore>節點中插入一個<book>節點:
   XmlDocument xmlDoc=new XmlDocument();
   xmlDoc.Load("bookstore.xml");
   XmlNode root=xmlDoc.SelectSingleNode("bookstore");//查找<bookstore>
   XmlElement xe1=xmlDoc.CreateElement("book");//創建一個<book>節點
   xe1.SetAttribute("genre","李贊紅");//設置該節點genre屬性
   xe1.SetAttribute("ISBN","2-3631-4");//設置該節點ISBN屬性
 
   XmlElement xesub1=xmlDoc.CreateElement("title");
   xesub1.InnerText="CS從入門到精通";//設置文本節點
   xe1.AppendChild(xesub1);//添加到<book>節點中
   XmlElement xesub2=xmlDoc.CreateElement("author");
   xesub2.InnerText="候捷";
   xe1.AppendChild(xesub2);
   XmlElement xesub3=xmlDoc.CreateElement("price");
   xesub3.InnerText="58.3";
   xe1.AppendChild(xesub3);
 
   root.AppendChild(xe1);//添加到<bookstore>節點中
   xmlDoc.Save("bookstore.xml");
//===============================================
結果爲:
<?xml version="1.0" encoding="gb2312"?>
<bookstore>
  <book genre="fantasy" ISBN="2-3631-4">
    <title>Oberon's Legacy</title>
    <author>Corets, Eva</author>
    <price>5.95</price>
  </book>
  <book genre="李贊紅" ISBN="2-3631-4">
    <title>CS從入門到精通</title>
    <author>候捷</author>
    <price>58.3</price>
  </book>
</bookstore>
 
2、修改節點:將genre屬性值爲“李贊紅“的節點的genre值改爲“update李贊紅”,將該節點的子節點<author>的文本修改爲“亞勝”。
    XmlNodeList nodeList=xmlDoc.SelectSingleNode("bookstore").ChildNodes;//獲取bookstore節點的所有子節點
   foreach(XmlNode xn in nodeList)//遍歷所有子節點
   {
    XmlElement xe=(XmlElement)xn;//將子節點類型轉換爲XmlElement類型
    if(xe.GetAttribute("genre")=="李贊紅")//如果genre屬性值爲“李贊紅”
    {
     xe.SetAttribute("genre","update李贊紅");//則修改該屬性爲“update李贊紅”
 
     XmlNodeList nls=xe.ChildNodes;//繼續獲取xe子節點的所有子節點
     foreach(XmlNode xn1 in nls)//遍歷
     {
      XmlElement xe2=(XmlElement)xn1;//轉換類型
      if(xe2.Name=="author")//如果找到
      {
       xe2.InnerText="亞勝";//則修改
       break;//找到退出來就可以了
      }
     }
     break;
    }
   }
 
   xmlDoc.Save("bookstore.xml");//保存。
//==================================================
最後結果爲:
<?xml version="1.0" encoding="gb2312"?>
<bookstore>
  <book genre="fantasy" ISBN="2-3631-4">
    <title>Oberon's Legacy</title>
    <author>Corets, Eva</author>
    <price>5.95</price>
  </book>
  <book genre="update李贊紅" ISBN="2-3631-4">
    <title>CS從入門到精通</title>
    <author>亞勝</author>
    <price>58.3</price>
  </book>
</bookstore>
 
3、刪除 <book genre="fantasy" ISBN="2-3631-4">節點的genre屬性,刪除 <book genre="update李贊紅" ISBN="2-3631-4">節點。
XmlNodeList xnl=xmlDoc.SelectSingleNode("bookstore").ChildNodes;
 
   foreach(XmlNode xn in xnl)
   {
    XmlElement xe=(XmlElement)xn;
    if(xe.GetAttribute("genre")=="fantasy")
    {
     xe.RemoveAttribute("genre");//刪除genre屬性
    }
    else if(xe.GetAttribute("genre")=="update李贊紅")
    {
     xe.RemoveAll();//刪除該節點的全部內容
    }
   }
   xmlDoc.Save("bookstore.xml");
//===========================================
最後結果爲:
<?xml version="1.0" encoding="gb2312"?>
<bookstore>
  <book ISBN="2-3631-4">
    <title>Oberon's Legacy</title>
    <author>Corets, Eva</author>
    <price>5.95</price>
  </book>
  <book>
  </book>
</bookstore>
 
4、顯示所有數據。
   XmlNode xn=xmlDoc.SelectSingleNode("bookstore");
 
   XmlNodeList xnl=xn.ChildNodes;
  
   foreach(XmlNode xnf in xnl)
   {
    XmlElement xe=(XmlElement)xnf;
    Console.WriteLine(xe.GetAttribute("genre"));//顯示屬性值
    Console.WriteLine(xe.GetAttribute("ISBN"));
 
    XmlNodeList xnf1=xe.ChildNodes;
    foreach(XmlNode xn2 in xnf1)
    {
     Console.WriteLine(xn2.InnerText);//顯示子節點點文本
    }
   }

#########################################################################

 

使用DataSet讀取數據:

 

XML文件:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <user id="1">
    <name>admin</name>
    <password>123456</sex>
  </user>
  <user id="2">
    <name>guest</name>
    <password>654321</password>
  </user>
  <upload>
    <saveToPath>/temp</saveToPath>
    <maxSize>10240</maxSize>
    <forbiddenFileExts>.exe|.jsp|.asp|.aspx</forbiddenFileExts>
  </upload>
  <InspectionInterval>3</InspectionInterval>
</configuration> 

 

這種有重複節點的XML最好用表結構來讀取
方法:
DataSet ds = new DataSet();            
ds.ReadXml(@"E:/XMLFile1.xml");//xml文件完整路徑
對於你的這段xml文件,ds會讀成3個表,configuration表(1行),user表(2行),upload表(1行);
例如要取 user id = 2時的name值,相當於取user表的第二行,name列的值,可以這樣:
string name = ds.Tables["user"].Rows[1]["name"].ToString();
取saveToPath值:
ds.Table["upload"].Rows[0]["saveToPath"]; 

 

多謝以上方法的原創作者,小弟受益匪淺!

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