認識XmlReader


摘要

XmlReader類是組成.NET的關鍵技術之一,極大地方便了開發人員對Xml的操作。通過本文您將對XmlReader有一個很好的認識,並將其應用到實際開發中。


 

目錄


 

1.概要

XmlReader 類是一個提供對 XML 數據的非緩存、只進只讀訪問的抽象基類。該類符合 W3C 可擴展標記語言 (XML) 1.0 和 XML 中的命名空間的建議。

XmlReader 類支持從流或文件讀取 XML 數據。該類定義的方法和屬性使您可以瀏覽數據並讀取節點的內容。

XmlReader類是一個抽象類,XmlTextReader,XmlValidatingReader,和XmlNodeReader類都繼承自XmlReader類。XmlReader類有很多方法和屬性用來讀取XML文件的內容、查找XML元素的深度、判斷當前元素的內容是否為空,以及導航XML的屬性等。

 

2.創建Xml讀取器

我們可以通過Create方法來創建一個XmlReader實例,也可以通過XmlReaderSettings類來配置XmlReader對象。使用XmlReaderSettings類的屬性啟用或禁用XmlReader對象的特定功能,然后將XmlReaderSettings對象傳遞給Create方法。

MSDN建議:

盡管在 .NET Framework 2.0 版中,Microsoft .NET Framework 包括 XmlReader 類的具體實現,例如 XmlTextReader、XmlNodeReader 和 XmlValidatingReader類,但是,我們建議您使用 Create 方法創建 XmlReader 實例。

通過使用 Create 方法和 XmlReaderSettings 類,您將得到下列好處:

  • 可以指定要在所創建的 XmlReader 對象上支持的功能。
  • XmlReaderSettings 類可以重復使用,以創建多個讀取器對象。可以使用相同的設置創建多個具有相同功能的讀取器。另外,可以修改 XmlReaderSettings 對象並創建具有不同功能集的新讀取器。
  • 可以將功能添加到現有讀取器中。Create 方法可以接受其他 XmlReader 對象。基礎 XmlReader 對象可以是用戶定義的讀取器或 XmlTextReader 對象,也可以是要添加附加功能的另一個 XmlReader 實例。
  • 充分利用 .NET Framework 2.0 版本的 XmlReader 類中增加的所有新功能。某些功能只能在通過 Create 方法創建的 XmlReader 對象上使用,例如更好的一致性檢查以及與 XML 1.0 建議的一致性。

提示:XmlReaderSettings 類的屬性設置可以參考:http://msdn.microsoft.com/zh-cn/library/9khb6435(v=vs.80).aspx

 實例化XmlReader:

1 XmlReaderSettings settings = new XmlReaderSettings();
2 settings.ConformanceLevel = ConformanceLevel.Fragment;
3 settings.IgnoreWhitespace = true;
4 settings.IgnoreComments = true;
5 XmlReader reader = XmlReader.Create("books.xml", settings);

 

3.訪問外部資源

XmlResolver類用於定位並訪問XmlReader對象所需的任何資源。XmlResolver可以用於執行以下操作:

  • 定位並打開 XML 實例文檔。
  • 定位並打開 XML 實例文檔所引用的任何外部資源。其中可以包括實體、文檔類型定義、架構等。
  • 如果資源存儲在要求身份驗證的系統上,System.Xml.XmlResolver.Credentials 屬性可以用於指定必要的憑據。

注意:如果未指定 XmlResolver,創建的讀取器將使用沒有用戶憑據的默認 XmlUrlResolver。XmlUrlResover解析由統一資源標識符 (URI) 命名的外部 XML 資源,是 System.Xml 命名空間中的所有類的默認解析器

 

以下代碼創建一個 XmlReader 實例,使用具有默認憑據的 XmlUrlResolver。

1 // Create a resolver with default credentials.
2 XmlUrlResolver resolver = new XmlUrlResolver();
3 resolver.Credentials = System.Net.CredentialCache.DefaultCredentials;
4
5 // Set the reader settings object to use the resolver.
6 settings.XmlResolver = resolver;
7
8 // Create the XmlReader object.
9 XmlReader reader = XmlReader.Create("http://ServerName/data/books.xml", settings);

 

4.讀取數據

讀取數據是處理XML文件最終目的,因此也是本文最重要的部分。下面將詳細討論如何通過XmlReader來讀取Xml數據。

4.1  當前節點位置

XmlReader 類提供了對 XML 流或文件的只進訪問。當前節點是讀取器當前所處的 XML 節點。所有調用的方法和執行的操作與當前節點相關,所有檢索到的屬性反映當前節點的值。

讀取器通過調用一種讀取方法(read方法)前進。重復調用該讀取方法可以將讀取器移至下一個節點。此類調用通常在 While 循環內執行。

下面的示例顯示了如何在流中定位來確定當前的節點類型。

 

View Code
 1 reader.MoveToContent();
2 // Parse the file and display each of the nodes.
3 while (reader.Read()) {
4 switch (reader.NodeType) {
5 case XmlNodeType.Element:
6 Console.Write("<{0}>", reader.Name);
7 break;
8 case XmlNodeType.Text:
9 Console.Write(reader.Value);
10 break;
11 case XmlNodeType.CDATA:
12 Console.Write("<![CDATA[{0}]]>", reader.Value);
13 break;
14 case XmlNodeType.ProcessingInstruction:
15 Console.Write("<?{0} {1}?>", reader.Name, reader.Value);
16 break;
17 case XmlNodeType.Comment:
18 Console.Write("<!--{0}-->", reader.Value);
19 break;
20 case XmlNodeType.XmlDeclaration:
21 Console.Write("<?xml version='1.0'?>");
22 break;
23 case XmlNodeType.Document:
24 break;
25 case XmlNodeType.DocumentType:
26 Console.Write("<!DOCTYPE {0} [{1}]", reader.Name, reader.Value);
27 break;
28 case XmlNodeType.EntityReference:
29 Console.Write(reader.Name);
30 break;
31 case XmlNodeType.EndElement:
32 Console.Write("</{0}>", reader.Name);
33 break;
34 }
35 }


 提示:XmlNodeType為節點類型,詳細信息可參考http://msdn.microsoft.com/zh-cn/library/3k5w5zc3(v=vs.80).aspx

 

4.2 讀取元素

下表介紹 XmlReader 類為處理元素提供的方法和屬性。

成員名稱

說明

IsStartElement

檢查當前節點是否是開始標記或空的元素標記。

ReadStartElement

檢查當前節點是否為元素並將讀取器推進到下一個節點。

ReadEndElement

檢查當前節點是否為結束標記並將讀取器推進到下一個節點。

ReadElementString

讀取純文本元素。

ReadToDescendant

將 XmlReader 前進到具有指定名稱的下一個子代元素。

ReadToNextSibling

將 XmlReader 前進到具有指定名稱的下一個同輩元素。

IsEmptyElement

檢查當前元素是否包含空的元素標記。此屬性使您能夠確定下面各項之間的差異:

  • <item num="123"/>(IsEmptyElement 為 true。)

  • <item num="123">(IsEmptyElement 為 false,盡管元素內容是空的。)

也就是說,IsEmptyElement 只是報告源文檔中的元素是否包含結束元素標記。

以下代碼使用 ReadStartElement 和 ReadString 方法讀取元素。

 1 using (XmlReader reader = XmlReader.Create("book3.xml")) {
2
3 // Parse the XML document. ReadString is used to
4 // read the text content of the elements.
5 reader.Read();
6 reader.ReadStartElement("book");
7 reader.ReadStartElement("title");
8 Console.Write("The content of the title element: ");
9 Console.WriteLine(reader.ReadString());
10 reader.ReadEndElement();
11 reader.ReadStartElement("price");
12 Console.Write("The content of the price element: ");
13 Console.WriteLine(reader.ReadString());
14 reader.ReadEndElement();
15 reader.ReadEndElement();
16
17 }

 

4.3 讀取屬性

XmlReader 類提供了各種方法和屬性來讀取屬性。屬性在元素上最常見。但是,XML 聲明和文檔類型節點上也允許使用屬性。

在位於某個元素節點上時,使用 MoveToAttribute 方法可以瀏覽該元素的屬性列表。調用了 MoveToAttribute 之后,節點屬性(例如 Name、NamespaceURI、Prefix 等)將反映該屬性的屬性,而不是其所屬的包含元素的屬性。

下表介紹專門為處理屬性而設計的方法和屬性。

成員名 說明

AttributeCount

獲取元素的屬性列表。

GetAttribute

獲取屬性的值。

HasAttributes

獲取一個值,該值指示當前節點是否有任何屬性。

IsDefault

獲取一個值,該值指示當前節點是否是從 DTD 或架構中定義的默認值生成的屬性。

Item

獲取指定屬性的值。

MoveToAttribute

移動到指定的屬性。

MoveToElement

移動到擁有當前屬性節點的元素。

MoveToFirstAttribute

移動到第一個屬性。

MoveToNextAttribute

移動到下一個屬性。

ReadAttributeValue

將屬性值分析為一個或多個 Text、EntityReference 或 EndEntity 節點。

 

實例1:使用 AttributeCount 屬性讀取某個元素的所有屬性。

1 // Display all attributes.
2 if (reader.HasAttributes) {
3 Console.WriteLine("Attributes of <" + reader.Name + ">");
4 for (int i = 0; i < reader.AttributeCount; i++) {
5 Console.WriteLine(" {0}", reader[i]);
6 }
7 // Move the reader back to the element node.
8 reader.MoveToElement();
9 }

 

實例2:在 While 循環中使用 MoveToNextAttribute 屬性讀取某個元素的所有屬性。

1 if (reader.HasAttributes) {
2 Console.WriteLine("Attributes of <" + reader.Name + ">");
3 while (reader.MoveToNextAttribute()) {
4 Console.WriteLine(" {0}={1}", reader.Name, reader.Value);
5 }
6 // Move the reader back to the element node.
7 reader.MoveToElement();
8 }

 

實例3:按名稱獲取屬性的值。

1 reader.ReadToFollowing("book");
2 string isbn = reader.GetAttribute("ISBN");
3 Console.WriteLine("The ISBN value: " + isbn);

 

提示:ReadToFollowing方法表示一直讀取,直到找到具有指定限定名的元素。使用此方法可以提高在 XML 文檔中查找命名元素的速度。 如果找到匹配的元素,它讓讀取器前進到與指定名稱匹配的下一個后續元素,並返回 true

 

4.4 讀取內容

1. 使用Value屬性

Value 屬性可以用於獲取當前節點的文本內容。返回的值取決於當前節點的節點類型。下表介紹每種可能的節點類型所返回的內容。

 

節點類型

Attribute

屬性的值。

CDATA

CDATA 節的內容。

Comment

注釋的內容。

DocumentType

內部子集。

ProcessingInstruction

全部內容(不包括指令目標)。

SignificantWhitespace

混合內容模型中任何標記之間的空白。

Text

文本節點的內容。

Whitespace

標記之間的空白。

XmlDeclaration

聲明的內容。

所有其他節點類型

空字符串。

 

2.利用ReadString方法

ReadString 方法以字符串的形式返回元素或文本節點的內容。

如果 XmlReader 位於某個元素上,ReadString 將所有文本、有效空白、空白和 CDATA 節節點串聯在一起,並以元素內容的形式返回串聯的數據。當遇到任何標記時,讀取器停止。這可以在混合內容模型中發生,也可以在讀取元素結束標記時發生。

如果 XmlReader 位於某個文本節點上,ReadString 將對文本、有效空白、空白和 CDATA 節節點執行相同的串聯。讀取器在第一個不屬於以前命名的類型的節點處停止。如果讀取器定位在屬性文本節點上,則 ReadString 與讀取器定位在元素開始標記上時的功能相同。它返回所有串聯在一起的元素文本節點。

 

3.利用ReadInnerXml方法

ReadInnerXml 方法返回當前節點的所有內容(包括標記)。不返回當前節點(開始標記)和對應的結束節點(結束標記)。例如,如果包含 XML 字符串 <node>this<child id="123"/></node>,ReadInnerXml 將返回 this<child id="123"/>。

節點類型 初始位置 XML 片斷 返回值 位於下列內容之后

Element

item1 開始標記上。

<item1>text1</item1><item2>text2</item2>

text1

item2 開始標記上。

Attribute

attr1 屬性節點上。

<item attr1="val1" attr2="val2">text</item>

val1

保留在 attr1 屬性節點上。

如果讀取器定位在葉節點上,則調用 ReadInnerXml 等效於調用 Read。

 

4.利用ReadOuterXml方法

ReadOuterXml 方法返回當前節點及其所有子級的所有 XML 內容,包括標記。其行為與 ReadInnerXml 類似,只是同時還返回開始標記和結束標記。

使用上表中的值,如果讀取器位於 item1 開始標記上,ReadOuterXml 將返回 <item1>text1</item1>。如果讀取器位於 attr1 屬性節點上,ReadOuterXml 將返回 attr1="val1"。

 

5. 一個簡單實例

將菜單food.xml的數據解析,並按一定的格式顯示出來。

food.xml數據格式如下:

 1 <?xml version="1.0" encoding="utf-8" ?> 
2 <breakfast_menu>
3 <food>
4 <name>Belgian Waffles</name>
5 <price>$5.95</price>
6 <description>two of our famous Belgian Waffles with plenty of real maple syrup</description>
7 <calories>650</calories>
8 </food>
9 <food>
10 <name>Strawberry Belgian Waffles</name>
11 <price>$7.95</price>
12 <description>light Belgian waffles covered with strawberries and whipped cream</description>
13 <calories>900</calories>
14 </food>
15 </breakfast_menu>

C#代碼:

View Code
 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Xml;
6
7 namespace myXmlReader
8 {
9 class Program
10 {
11 static void Main(string[] args)
12 {
13 XmlReader reader = XmlReader.Create(@"E:\kemi\CodeNow\Project\XmlReader\food.xml");//創建XmlReader實例
14
15 while (reader.Read())
16 {
17 if (reader.NodeType.Equals(XmlNodeType.Element))//判斷節點類型
18 {
19 switch (reader.Name)
20 {
21
22 case "breakfast_menu":
23 Console.WriteLine("===========breakfast menu==========");
24 break;
25 case "name":
26 Console.WriteLine("Name:{0}", reader.ReadString());//使用ReadString讀取數據
27 break;
28 case "price":
29 Console.WriteLine("Price:{0}", reader.ReadString());
30 break;
31 case "description":
32 Console.WriteLine("Description:{0}", reader.ReadInnerXml());//使用ReadInnerXml讀取數據
33 break;
34 case "calories":
35 Console.WriteLine("Description:{0}", reader.ReadInnerXml());
36 break;
37 default:
38 Console.WriteLine("");
39 break;
40 }
41 }
42 }
43
44 Console.Read();
45 }
46 }
47 }


輸出結果:

xmlreader
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM