用 XmlReader 读取 XML

用 XmlReader 读取 XML

XmlReader 类是一个提供非缓存的、只进只读访问的抽象基类。XmlReader 类检查 XML 格式是否正确,并且在遇到错误时引发 XmlExceptions。它可以读取流或文档,并且实现在由位于 www.w3.org/TR/REC-xml-names 的 W3C 所提供的建议中概述的命名空间要求。

作为抽象基类,它使得您能够自定义自己的类型的读取器或扩展 XmlTextReaderXmlValidatingReaderXmlNodeReader 类的当前实现。但是,.NET Framework 1.1 版中针对 XmlReader 实现的安全约束限制了继承 XmlTextReaderXmlValidatingReader 的能力。在 .NET Framework 1.0 版中,任何组件都可以继承 XmlTextReaderXmlValidatingReader。通过在 .NET Framework 1.1 版中实现对 XmlTextReaderXmlValidatingReader 构造函数的继承要求,可信的组件现在只是那些能够继承 XmlTextReaderXmlValidatingReader 的组件。

XmlReader 类还定义了使您能够从 XML 提取数据或跳过不需要的记录的方法。XmlReader 与 SAX 模型不同,后者是具有将事件推送到应用程序的分析器的推送模型。有关与 SAX 比较的更多信息,请参见将 XmlReader 与 SAX 读取器比较

XmlReader 类具有进行以下操作的方法:

  • 当 XML 内容在整体上完全可用时(如 XML 文本文件)读取该内容。
  • 找出 XML 元素堆栈的深度。
  • 确定元素是具有内容还是为空。
  • 读取并定位属性。
  • 跳过元素和它们的内容。

XmlReader 类的某些属性返回信息,例如:

  • 当前节点的类型和名称。
  • 当前节点的内容。

XmlReader 类的实现扩展了基类,而它们的设计也多种多样,能够支持不同方案的需要。下表说明了 XmlReader 类的实现。

说明
XmlTextReader 类 读取字符流。它是一个只进读取器,具有返回有关内容和节点类型的数据的方法。没有文档类型定义 (DTD) 或架构支持。
XmlNodeReader 类 提供 XML 文档对象模型 (DOM) API(如 XmlNode 树)的分析器。获取一个 XmlNode,它将返回在 DOM 树中查找到的任何节点,包括实体引用节点。没有 DTD 或架构验证支持,但它可以解析定义在 DTD 中的实体。
XmlValidatingReader 类 提供具有 DTD、XML 架构定义语言 (XSD) 架构或 XML-数据精简 (XDR) 架构支持的完全符合的验证或非验证 XML 分析器。获取 XmlTextReader 并在顶部设置验证服务层。
自定义的 XML 读取器的创建 使得能够实现 XmlReader 的开发人员定义的派生。
注意   ?? XmlTextReaderXmlValidatingReader 可以读取的文件的大小有限制。它们无法读取大于 2 千兆字节的文件。如果可能,可将源文件分割为多个较小的文件。

XsltReader 是不具有公共构造函数的另一种实现。它是作为调用 XslTransform 类的 Transform 方法的结果创建的。XsltReader 提供以下功能:

  • 强制 XML 必须采用正确格式的规则。
  • 不针对 DTD 或架构进行验证。
  • 不扩展默认特性,这是因为 DTD 信息(DOCTYPE 节点)不在 XPath 数据模型中公开。请参见 XmlReader.IsDefault 属性。如果您需要在应用转换前在源文档中扩展默认特性,则需要通过 XmlValidatingReader 加载数据存储区(例如 XmlDocument)。

XmlTextReaderXmlValidatingReaderXmlNodeReader,这些类中的每一个均被设计为支持不同的方案。下表描述用于各种方案的读取器以及提供给 ValidationType 属性的值。

方案 要使用的读取器 ValidationType 属性
需要更高的性能并且不需要任何 DTD 和架构支持。 XmlTextReader 不可用。
要求 XML 格式正确,包括外部实体和符合所提供的 DTD 的 DocType。 XmlTextReader 不可用。
需要 XML 对于 DTD 是有效且格式正确的。 XmlValidatingReader AutoDTD
需要 XML 格式正确且要针对某个架构对它进行验证。 XmlValidatingReader 当没有 DTD 可用时为 Auto,否则为 XDR 架构。
需要 XML 在从 XmlNode 对 XML 数据进行流式处理时格式正确。 XmlNodeReader 不可用。

下表描述如何设置各种读取器的 XmlResolverXmlTextReader.Normalization 属性以便实现各种方案。

Normalization 属性在设置为 true 时,将正常化文本和空白节点中的行尾字符,并根据它们的类型正常化属性值。因此,将 Normalization 属性设置为 true 会导致性能比将其设置为 false(默认值)时更低。有关更多信息,请参见 XmlTextReader.Normalization 属性

XmlResolver 属性用于解析以 URI 命名的外部资源(如外部 DTD)或定位一个架构。有关将 XmlResolver 属性用于不同读取器的更多信息,请参见使用 XmlResolver 解析资源

方案 XmlResolver Normalization 属性
需要更高的性能并且不需要任何 DTD 和架构支持。 设置为空引用。有关更多信息,请参见 XmlTextReader.XmlResolver 属性 设置为 false
需要文档格式正确,包括外部实体和符合所提供的 DTD 的 DocType。 设置为非空引用。所有外部实体必须都是可解析的。有关更多信息,请参见 XmlTextReader.XmlResolver 属性 设置为 true
需要文档格式正确,并且需要对于 DTD XML 是有效的。 设置为非空引用。所有外部实体必须都是可解析的。有关更多信息,请参见 XmlValidatingReader.XmlResolver 属性 传递到 XmlValidatingReader 之前对 XmlTextReader 设置为 true
需要文档格式正确并且需要架构验证。 设置为非空引用。所有外部实体必须都是可解析的。有关更多信息,请参见 XmlValidatingReader.XmlResolver 属性 传递到 XmlValidatingReader 之前对 XmlTextReader 设置为 true
需要在从 XmlNode 对 XML 数据进行流式处理时文档格式正确。 不可用。 不可用。

XmlValidatingReader 提供了对 XmlTextReader 的验证服务。有关更多信息,请参见使用 XmlValidatingReader 进行 XML 验证

XmlReader 中的当前节点位置

XmlReader 类提供了对 XML 流或文件的只进访问。当前节点是读取器当前所在的 XML 节点,所有调用的方法和采取的操作都是相对于此当前节点的,并且检索的所有属性都反映了当前节点的值。

读取器是通过对其中一个 Read 方法的调用推进的。下面的示例显示了如何在流中定位来确定当前的节点类型。

[Visual Basic]
Option Explicit
Option Strict

Imports System
Imports System.IO
Imports System.Xml

Namespace Test
   
   Public Class MyApp
      
      Public Shared Sub Main()
         Dim rdr As New XmlTextReader("books.xml")
         ReadandWrite(rdr)
      End Sub
      
      Public Shared Sub ReadandWrite(rdr As XmlReader)
         'Read each node in the tree.
         While rdr.Read()
            Select Case rdr.NodeType
               Case XmlNodeType.Element
                  Console.Write(("<" & rdr.Name))
                  While rdr.MoveToNextAttribute()
                     Console.Write((" " & rdr.Name & "='" & rdr.Value & "'"))
                  End While
                  Console.Write(">")
                  If rdr.IsEmptyElement = True Then
                     Console.Write("#EmptyElement")
                  Else
                     Console.Write("#Element")
                  End If
               Case XmlNodeType.Text
                  Console.Write(rdr.Value)
                  Console.Write("#Text")
               Case XmlNodeType.CDATA
                  Console.Write(rdr.Value)
               Case XmlNodeType.ProcessingInstruction
                  Console.Write(("<?" & rdr.Name & " " & rdr.Value & "?>"))
               Case XmlNodeType.Comment
                  Console.Write(("<!--" & rdr.Value & "-->"))
               Case XmlNodeType.Document
                  Console.Write("<?xml version='1.0'?>")
               Case XmlNodeType.Whitespace
                  Console.Write(rdr.Value)
               Case XmlNodeType.SignificantWhitespace
                  Console.Write(rdr.Value)
               Case XmlNodeType.EndElement
                  Console.Write(("</" & rdr.Name & ">"))
                  Console.Write("#EndElement")
            End Select
         End While
      End Sub
   End Class
End Namespace
[C#]
using System;
using System.IO;
using System.Xml;
namespace Test
{
   public class MyApp 
   {
     public static void Main()
     {
        XmlTextReader rdr = new XmlTextReader("books.xml");
        ReadandWrite(rdr);
     }
     public static void ReadandWrite(XmlReader rdr)
     {
        //Read each node in the tree.
        while (rdr.Read())
        {
           switch (rdr.NodeType)
           {
             case XmlNodeType.Element:
               Console.Write("<" + rdr.Name);
               while (rdr.MoveToNextAttribute())
                 Console.Write(" " + rdr.Name + "='" + rdr.Value + "'");
                 Console.Write(">");
                 if (rdr.IsEmptyElement == true)
                    Console.Write("#EmptyElement");
                 else
                    Console.Write("#Element");
                 break;
               case XmlNodeType.Text:
                 Console.Write(rdr.Value);
                 Console.Write("#Text");
               break;
               case XmlNodeType.CDATA:
                 Console.Write(rdr.Value);
               break;
               case XmlNodeType.ProcessingInstruction:
                 Console.Write("<?" + rdr.Name + " " + rdr.Value + "?>");
               break;
               case XmlNodeType.Comment:
                 Console.Write("<!--" + rdr.Value + "-->");
               break;
               case XmlNodeType.Document:
                 Console.Write("<?xml version='1.0'?>");
               break;
               case XmlNodeType.Whitespace:
                 Console.Write(rdr.Value);
               break;
               case XmlNodeType.SignificantWhitespace:
                 Console.Write(rdr.Value);
               break;
               case XmlNodeType.EndElement:
                 Console.Write("</" + rdr.Name + ">");
                 Console.Write("#EndElement");
               break;
            }
         }
      }
   }
}

重复调用 Read 将移到下一个节点,并且这种调用通常在 while 循环中执行。

XmlReader 中可用的属性并不是在每个节点类型上都可用。例如,如果当前节点为元素且以正斜线字符“/>”结尾,则 IsEmptyElement 返回 true。对其他任何节点类型调用该属性都返回 false,这是因为该属性不适用于其他节点类型。下面的示例显示了特性和元素属性的用法。它显示了如何检查一个元素是否具有特性。如果元素有特性,则该示例显示如何使用 AttributeCount 属性依次通过这些特性。

[Visual Basic]
Public Sub DisplayAttributes(reader As XmlReader)
    If reader.HasAttributes Then
        Console.WriteLine(("Attributes of <" & reader.Name & ">"))
        Dim i As Integer
        For i = 0 To reader.AttributeCount - 1
            reader.MoveToAttribute(i)
            Console.Write(" {0}={1}", reader.Name, reader.Value)
        Next i
        reader.MoveToElement() 'Moves the reader back to the element node.
    End If
End Sub 'DisplayAttributes
[C#]
public void DisplayAttributes(XmlReader reader)
{
  if (reader.HasAttributes)
  {
    Console.WriteLine("Attributes of <" + reader.Name + ">");
    for (int i = 0; i < reader.AttributeCount; i++)
    {
      reader.MoveToAttribute(i);
      Console.Write(" {0}={1}", reader.Name, reader.Value);
    }
    reader.MoveToElement(); //Moves the reader back to the element node.
  }
}

MoveToAttribute 方法定位在元素节点上时,它使您能够在该元素的特性列表中定位。与此类似,当读取器定位在特性节点上时,对 MoveToElement 方法的调用将把读取器定位在拥有当前属性节点的元素处。这是用于在通过元素的特性定位后移回该元素的方法。有关可用方法的完整列表,请参见 XmlReader 成员

下面的示例读取一个具有 DTD 的 XML 流并打印各节点的节点属性。该示例还通过使用 HasAttributes 属性检查节点是否具有特性。如果有特性,则代码使用 MoveToNextAttribute 方法并打印出特性名称、本地名称和命名空间 URI。

[Visual Basic]
Public Shared Sub Main()
   Dim stream As New StringReader("<!DOCTYPE test [<!ELEMENT test  (item|bar)*><!ELEMENT item (item*)><!ATTLIST item xml:space (default|preserve) #IMPLIED><!ELEMENT bar (#PCDATA|b|i)*><!ELEMENT b (#PCDATA)><!ELEMENT i (#PCDATA)>]> <test> <item> <item xml:space=""preserve"">  <item/>  </item>  </item>  <bar>  <b>This</b>  <i>is</i>  <b>a test</b>  </bar> </test> ")
   Dim myTxtReader As New XmlTextReader(stream)
   Dim myReader As New XmlValidatingReader(myTxtReader)
   myTxtReader.ValidationType = ValidationType.None
   While myReader.Read()
      WriteNodeInfo(myReader)
   End While
End Sub 'Main
 
Private Shared Sub WriteNodeInfo(xmlreader As XmlReader)
   Console.WriteLine("*****************************************************")
   Console.WriteLine()
   Console.WriteLine(("NodeType  = " + xmlreader.NodeType))
   Console.WriteLine(("NodeName  = " + xmlreader.Name))
   Console.WriteLine(("NodeLocalName  = " + xmlreader.LocalName))
   Console.WriteLine(("NodeNamespace  = " + xmlreader.NamespaceURI))
   Console.WriteLine(("NodePrefix  = " + xmlreader.Prefix))
   Console.WriteLine(("NodeHasValue  = " + xmlreader.HasValue))
   Console.WriteLine(("NodeValue = [" + xmlreader.Value + "]"))
   Console.WriteLine(("NodeDepth = " + xmlreader.Depth))
   Console.WriteLine(("IsEmptyElement = " + xmlreader.IsEmptyElement.ToString()))
   Console.WriteLine(("IsDefault = " + xmlreader.IsDefault.ToString()))
   Console.WriteLine(("QuoteChar = " + xmlreader.QuoteChar))
   Console.WriteLine(("XmlSpace = " + xmlreader.XmlSpace))
   Console.WriteLine(("XmlLang = " + xmlreader.XmlLang))
   Console.WriteLine(("AttributeCount = " + xmlreader.AttributeCount))
   Console.WriteLine(("HasAttributes = " + xmlreader.HasAttributes.ToString()))
   Console.WriteLine(("EOF = " + xmlreader.EOF.ToString()))
   Console.WriteLine(("ReadState = " + xmlreader.ReadState.ToString()))
   If xmlreader.HasAttributes Then
      While True = xmlreader.MoveToNextAttribute()
         Console.WriteLine(("AttributeName = " + xmlreader.Name))
         Console.WriteLine(("AttributeLocalName = " + xmlreader.LocalName))
         Console.WriteLine(("AttributeNamespace = " + xmlreader.NamespaceURI))
      End While
   End If
   Console.WriteLine()
   Console.WriteLine("***************************************************")
   Console.WriteLine()
End Sub 'WriteNodeInfo
[C#]
public static void Main() {
    StringReader stream = new StringReader ("<!DOCTYPE test [<!ELEMENT test  (item|bar)*><!ELEMENT item (item*)><!ATTLIST item xml:space (default|preserve) #IMPLIED><!ELEMENT bar (#PCDATA|b|i)*><!ELEMENT b (#PCDATA)><!ELEMENT i (#PCDATA)>]> <test> <item> <item xml:space=\"preserve\">  <item/>  </item>  </item>  <bar>  <b>This</b>  <i>is</i>  <b>a test</b>  </bar> </test> ");
    XmlTextReader myTxtReader = new XmlTextReader (stream);
    XmlValidatingReader myReader = new XmlValidatingReader (myTxtReader);
    myTxtReader.ValidationType = ValidationType.None;
    while (myReader .Read())
        WriteNodeInfo(myReader );
}

private static void WriteNodeInfo(XmlReader xmlreader) {
    Console.WriteLine("*****************************************************");
    Console.WriteLine();
    Console.WriteLine("NodeType  = " + xmlreader.NodeType );            
    Console.WriteLine("NodeName  = " + xmlreader.Name);           
    Console.WriteLine("NodeLocalName  = " + xmlreader.LocalName );            
    Console.WriteLine("NodeNamespace  = " + xmlreader.NamespaceURI);       
    Console.WriteLine("NodePrefix  = " + xmlreader.Prefix);          
    Console.WriteLine("NodeHasValue  = " + xmlreader.HasValue);            
    Console.WriteLine("NodeValue = [" + xmlreader.Value +"]");          
    Console.WriteLine("NodeDepth = " + xmlreader.Depth);          
    Console.WriteLine("IsEmptyElement = " + xmlreader.IsEmptyElement.ToString());  
    Console.WriteLine("IsDefault = " + xmlreader.IsDefault.ToString()); 
    Console.WriteLine("QuoteChar = " + xmlreader.QuoteChar);            
    Console.WriteLine("XmlSpace = " + xmlreader.XmlSpace);           
    Console.WriteLine("XmlLang = " + xmlreader.XmlLang);          
    Console.WriteLine("AttributeCount = " + xmlreader.AttributeCount);
    Console.WriteLine("HasAttributes = " + xmlreader.HasAttributes.ToString());
    Console.WriteLine("EOF = " + xmlreader.EOF.ToString());          
    Console.WriteLine("ReadState = " + xmlreader.ReadState.ToString());            
    if (xmlreader.HasAttributes)
    {
      while (true== xmlreader.MoveToNextAttribute())
      {
         Console.WriteLine("AttributeName = "+ xmlreader.Name);
         Console.WriteLine("AttributeLocalName = "+ xmlreader.LocalName);
         Console.WriteLine("AttributeNamespace = "+ xmlreader.NamespaceURI);
      }
    }
    Console.WriteLine();
    Console.WriteLine("***************************************************");
    Console.WriteLine();
}

前三个节点的输出:

*****************************************************

NodeType  = DocumentType
NodeName  = test
NodeLocalName  = test
NodeNamespace  = 
NodePrefix  = 
NodeHasValue  = True
NodeValue = [<!ELEMENT test  (item|bar)*><!ELEMENT item (item*)><!ATTLIST item xml:space (default|preserve) #IMPLIED><!ELEMENT bar (#PCDATA|b|i)*><!ELEMENT b (#PCDATA)><!ELEMENT i (#PCDATA)>]
NodeDepth = 0
IsEmptyElement = False
IsDefault = False
QuoteChar = "
XmlSpace = None
XmlLang = 
AttributeCount = 0
HasAttributes = False
EOF = False
ReadState = Interactive

***************************************************

*****************************************************

NodeType  = Whitespace
NodeName  = 
NodeLocalName  = 
NodeNamespace  = 
NodePrefix  = 
NodeHasValue  = True
NodeValue = [ ]
NodeDepth = 0
IsEmptyElement = False
IsDefault = False
QuoteChar = "
XmlSpace = None
XmlLang = 
AttributeCount = 0
HasAttributes = False
EOF = False
ReadState = Interactive

***************************************************

*****************************************************

NodeType  = Element
NodeName  = test
NodeLocalName  = test
NodeNamespace  = 
NodePrefix  = 
NodeHasValue  = False
NodeValue = []
NodeDepth = 0
IsEmptyElement = False
IsDefault = False
QuoteChar = "
XmlSpace = None
XmlLang = 
AttributeCount = 0
HasAttributes = False
EOF = False
ReadState = Interactive

***************************************************

有关所有节点类型的列表,请参见 XML 节点类型

XmlReader 的属性设置

XmlReader 类具有一些可以在读取时修改的属性,以及一些在读取开始后被更改时并不会使新设置影响读取的其他属性。如果默认值不合适,则需要在开始读取前将这些属性设置为正确的值。但是,某些属性可以在开始读取后修改。对于不能在调用 Read 后设置的属性,读取器将引发异常。下表显示可以在读取开始之后修改的属性。

属性 是否可以修改
XmlTextReader Namespaces
XmlTextReader WhitespaceHandling
XmlTextReader Normalization
XmlTextReader XmlResolver
XmlValidatingReader Namespaces
XmlValidatingReader EntityHandling
XmlValidatingReader XmlResolver
XmlValidatingReader ValidationType

XmlValidatingReaderXmlResolver 属性传播到所包含的 XmlTextReader 类。XmlNodeReader 类没有可以设置的属性。

读取元素和特性内容

为了读取调用中的元素和特性的内容,XmlReader 提供了 ReadInnerXmlReadOuterXml 方法。当定位在节点上时,ReadInnerXml 属性提取该节点中的所有内容,包括标记(从元素标记之后开始,直到元素结束标记)。在 ReadInnerXml 调用后,XmlReader 将被定位在结束元素标记之后。假定下列 XML 输入:

输入

<Book>
 <Price Retail="29.95" />
 <Title BookTitle="My First Book" author="me" />
</Book>

这是当读取器定位在 Book 元素上时调用 ReadInnerXml 所返回的输出:

 <Price Retail="29.95" />
 <Title BookTitle="My First Book" author="me" />

ReadInnerXml 将读取器定位在正在被读取的元素的结束标记之后。这意味着对于上面的输入,当前节点是 </Book> 结束元素(假定存在)之后的节点。执行 Read 方法将把它再向前推进一个元素。以下代码示例显示了在调用 ReadInnerXml 后流中的当前节点,以及在 ReadInnerXml 之后执行 Read 如何将读取器又向前推进一个节点。

[C#]
public static void Main() 
{
    string text = @"<book><one><title>ABC</title></one><two><price>24.95</price></two></book>";
    XmlTextReader reader = new XmlTextReader(new StringReader(text));
    reader.WhitespaceHandling = WhitespaceHandling.None;

    // Moves the reader to the 'book' node.
    reader.MoveToContent(); 

    // Moves the reader to the 'one' node.
    reader.Read(); 
    reader.MoveToContent();

    // Reads the inner XML of the 'one' node, which is the entire 'title'
    // node, and outputs <title>ABC</title>. 
    Console.WriteLine(reader.ReadInnerXml()); 

    // The reader is now positioned on the 'two' node.
    Console.WriteLine(reader.Name);

    // Calling Read will advance the reader beyond the 'two' node to 
    // the 'price' node.
    reader.Read();
    // Outputs the node of 'price'.
    Console.WriteLine(reader.Name);
}

该代码的输出是:

<title>ABC</title>

two

price

ReadInnerXml 根据 XmlNodeType 分析 XML 并返回内容。下表显示了元素和特性的示例内容、从对 ReadInnerXml 的调用返回的值以及该调用后读取器的位置。

节点类型 子内容 返回值 位置
Element <myelem> text </myelem> text 在结束元素 </myelem> 之后的节点上
Attribute <myelem attr1="val1" attr2="val2"> text </myelem> val1 保持在特性节点“attr1”上。

其他所有的 XmlNodeType 都返回 string.Empty

除返回值包括开始标记和结束标记外,ReadOuterXml 方法在行为上类似于 ReadInnerXml 方法。当定位在叶节点上时,该方法与执行 Read 操作相同。

根据当前的 XmlNodeTypeReadOuterXml 分析 XML 并返回各种子内容。下表显示了元素和特性的示例内容、从对 ReadOuterXml 的调用返回的值以及读取器在此调用后的位置。

节点类型 子内容 返回值 位置
Element <elem1> text </elem1> <elem1> text </elem1> 定位在 </elem1> 标记后。
Attribute <elem1 attr1="attrValue1" attr2="attrValue2" > text </elem1> attr1="attrValue1" 定位在特性节点“attr1”上。

其他所有节点类型都将 string.Empty 返回到 ReadOuterXml

用 XmlReader 跳过内容

跳过内容的方法有两种。一种方法是调用使用 MoveToContent 方法直接移动到内容的方法。另一种方法是直接调用 Skip 方法,该方法从当前节点跳过子节点。

直接移动到内容

若要移动到内容,请使用 MoveToContent 方法。该方法检查当前节点以查看它是否是内容节点。内容节点被定义为任意 Text、CDATA、Element、EndElement、EntityReference 或 EndEntity 节点。如果该节点不是前述节点类型之一,则将跳过该节点并跳到下一个节点或文件尾。它一直跳,直到找到该类型的节点或到文件的结尾才停止。换句话说,它跳过下列节点类型:

  • XmlDeclaration
  • ProcessingInstruction
  • DocumentType
  • Comment
  • Attribute
  • Whitespace
  • SignificantWhitespace

如果应用程序只需要内容,则使用这种类型的内容定位更有效率,而不是调用 Read,后一种做法将读取器移动到下一个节点并强制应用程序测试节点类型,然后确定是否存在要读取的内容,如果有则读取它。

如果应用程序定位在特性节点上,则调用 MoveToContent 将把当前节点位置移动到该特性所属的元素。如果应用程序已经定位在内容节点上,则 MoveToContent 调用将把 NodeType 属性的值返回到应用程序。这些行为使应用程序能够跳过随机的 XML 标记。例如,考虑以下 XML 输入:

<?xml version="1.0">
<!DOCTYPE price SYSTEM "abc">
<!––the price of the book –->
<price>123.4</price>

下列代码查找 price 元素“123.4”并将其文本内容转换为双精度型:

[Visual Basic]
If readr.MoveToContent() = XmlNodeType.Element And readr.Name = "price" Then
   _price = XmlConvert.ToDouble(readr.ReadString())
End If
[C#]
if (readr.MoveToContent() == XmlNodeType.Element && readr.Name =="price")
{
    _price = XmlConvert.ToDouble(readr.ReadString());
}

在另外一个示例中,MoveToContent 常常用于查找 XML 文件中的 DocumentElement 节点。假定有下面这个称为 file.xml 的 XML 输入文件:

<?xml encoding="utf-8"?>
<!-- Can have comment and DOCTYPE nodes here to skip past here -->
<phone a="2" b="N">
<data>
   <d1>Data</d1>
   <d2>More Data</d2>
   <d3>Some More Data</d3>
</data>
</phone>

下列代码将读取器定位到 DocumentElement 节点 <phone> 上:

[Visual Basic]
Dim doc as XmlDocument = New XmlDocument()
Dim treader as New XmlTextReader("file.xml")
treader.MoveToContent()        
[C#]
XmlDocument doc = new XmlDocument();
XmlTextReader treader = new XmlTextReader("file.xml");
treader.MoveToContent();

使用 Skip 方法跳过数据

Skip 方法跳过当前的元素。如果节点类型为 XmlNodeType.Element,则调用 Skip 将跳过该元素的所有内容和元素结束标记。

例如,如果您有下列 XML:

<a name="facts" location="123">
<x/> 
abc 
<y/>
</a>
<b>
...
</b>

并且您定位在 <a> 节点或它的任何一个特性上时,调用 Skip 将把您定位在 <b> 节点上。如果定位在叶节点上,如 x 或文本节点 abc 上,则 Skip 将跳到下一个节点,这意味着实际上它的行为与调用 Read 一样。

Skip 将格式正确的规则应用于内容。

用 XmlTextReader 读取 XML 数据

XmlTextReader 类是 XmlReader 的实现,它提供快速的,性能优良的分析器。它强制 XML 必须采用正确格式的规则。由于它既没有 DTD 信息,也没有架构信息,因此它既不是验证分析器也不是非验证分析器。它可以读取块中的文本或从流中读取字符。

XmlTextReader 提供了下列功能:

  • 强制 XML 必须采用正确格式的规则。
  • 检查 DTD 的格式是否正确。然而,并不将 DTD 用于验证、扩展实体引用或添加默认属性。
  • 不针对 DTD 或架构进行验证。
  • 检查 DOCTYPE 节点是否格式正确。
  • 检查实体是否格式正确。对于 EntityReference 节点类型,返回单个空 EntityReference 节点。空 EntityReference 节点是 Value 属性为 string.Empty 的节点。这是因为您没有用来扩展实体引用的 DTD 或架构。XmlTextReader 确保整个 DTD(包括 EntityReference 节点)格式正确。
  • 提供性能优良的 XML 分析器,原因是 XmlTextReader 没有涉及验证检查的系统开销。

XmlTextReader 可以从不同输入(如流对象、TextReader 对象以及标识本地文件位置或 Web 站点的 URL)读取数据。

XmlTextReader 使用 XmlResolver 定位外部资源(如 DTD),所以它可以检查 DTD 以查看它们是否格式正确。有关 XmlResolver 的更多信息,请参见使用 XmlResolver 解析资源

编码声明 <?xml version="1.0" encoding="ISO-8859-5"?> 包含设置文档的编码的编码属性。XmlTextReader 有一个 Encoding 属性,它返回在 XML 声明中的编码属性中找到的字符编码。如果未找到编码属性,则文档的默认值将设置为 UTF-8。

如果读取了外部资源(例如用于扩展实体引用或架构文件的 DTD),则编码将设置为在外部引用中找到的编码值。如果在外部引用中没有找到编码,则默认值设置为 UTF-8。XmlTextReader 支持许多编码,这是由于它使用 System.Text.Encoding Class。因此,该类支持的所有编码也受 XmlTextReader 支持。唯一不支持的编码是将 <?xml 序列映射到 UTF-8 以外的不同字节值(如 UTF-7 和 EBCDIC)的编码。

用 XmlNodeReader 读取节点树

XmlNodeReader 提供给定 DOM 节点子树的读取器。它从该子树读取并返回节点,包括实体引用节点。

XmlNodeReader 提供了下列功能:

  • 强制执行 XML 结构正确性规则。
  • 如果在 XmlDocument 中存在 DTD 信息,则扩展默认特性和实体。有关获取默认特性信息的更多信息,请参见 XmlReader.IsDefault 属性

XmlDocument 创建 XmlNodeReader

[Visual Basic]
Dim doc As New XmlDocument()
doc.Load("MyXml.xml")
Dim nodereader As New XmlNodeReader(doc)
While nodereader.Read()
   ' Read the XmlDocument as a stream of XML
End While
[C#]
XmlDocument doc = new XmlDocument();
doc.Load("MyXml.xml");
XmlNodeReader nodereader = new XmlNodeReader (doc);
while (nodereader.Read()) {
    // Read the XmlDocument as a stream of XML
}

也可以用 XmlDocument 中的任何 XmlNode 构造 XmlNodeReader

下面的示例使用 Select 方法和 XPath 表达式移动到 XmlDocument 中的某个特定节点。然后,它在该位置创建 XmlNodeReader。XML 输入文件 test.xml 包含下列数据:

<root>
   <child>
      Child Text
   </child>
</root>
[Visual Basic]
Imports System
Imports System.Xml

Public Class Test
   
    Public Shared Sub Main()
        Dim doc As New XmlDocument()
        doc.Load("test.xml")
        Dim child As XmlNode = doc.SelectSingleNode("/root/child")
        If Not (child Is Nothing) Then
            Dim nr As New XmlNodeReader(child)
            While nr.Read()
                Console.WriteLine(nr.Value)
            End While
        End If
    End Sub 'Main
End Class 'Test
[C#]
using System;
using System.Xml;
public class Test {
   public static void Main() {
      XmlDocument doc = new XmlDocument();
      doc.Load("test.xml");
      XmlNode child = doc.SelectSingleNode("/root/child");
      if (child != null) {
         XmlNodeReader nr = new XmlNodeReader(child );
         while (nr.Read() )
            Console.WriteLine( nr.Value );
      }
   }
}

将 XmlReader 和 XmlNameTable 一起使用来进行对象比较

XmlNameTable 类使 XmlReader 类的实现能够在分析数据或对 XML 文档执行比较操作时使用指针比较,而不是字符串比较。在比较和使用元素和特性名时,使用此表将提高 XmlReader 派生类的性能。

XmlNameTable 是一个抽象基类,NameTable 是它的一个实现。NameTable 包含元素和属性名的原子化的版本以及命名空间 URI 和前缀。如果应用程序正对名称进行大量比较,则它可以创建 NameTable。用户可以从读取器的 NameTable 属性获取读取器正在使用的 NameTable。有关原子化的说明,请参见 XmlNameTable 类

应用程序可以使用 Add 方法将名称添加到该表中。下面的示例显示比较是通过使用 Equals 方法或 == 运算符完成的,它确定在方法调用中提供的对象是否是与当前对象相同的实例。

[Visual Basic]
Dim cust As Object = reader.NameTable.Add("Customer")
While reader.Read()
   ' The "if" uses efficient pointer comparison.
   If cust Is reader.Name Then
      ...
   End If
End While

[C#]
object cust = reader.NameTable.Add("Customer");
while (reader.Read())
{
   // The "if" uses efficient pointer comparison.
   if (cust == reader.Name)   
   {
      ...
   }
}

自定义的 XML 读取器的创建

自定义 XML 读取器使应用程序能够扩展 XmlReaderXmlTextReader,或者定义它自己的自定义读取器。

扩展 XmlTextReader 的示例

下面是一个显示如何扩展 XmlTextReader 以创建将特性转换为元素的读取器的示例。重写的 Read 提供了跟踪当前节点类型的逻辑,并且如果当前节点类型是特性的话,将使用 XmlNodeType.NameXmlNodeType.Value 属性把它作为元素节点类型来公开。

[Visual Basic]
Option Explicit
Option Strict

Imports System
Imports System.IO
Imports System.Text
Imports System.Xml
Imports System.Xml.XPath

Public Class AttrToElementReader
   Inherits XmlTextReader

   Private _ReadAttributes As Boolean = False
   Private _ReadAttributeValue As Boolean = False
   Private _AttributeName As String = String.Empty
   Private _NodeType As XmlNodeType = XmlNodeType.None
   
   Public Sub New(fileName As String)
      MyBase.New(fileName)
      MyBase.WhitespaceHandling = WhitespaceHandling.None
      ' Intentionally Empty
   End Sub   
   
   Public Overrides Function Read() As Boolean
      If Not _ReadAttributes Then
         Dim baseRead As Boolean = MyBase.Read()
         _ReadAttributes = baseRead And XmlNodeType.Element = MyBase.NodeType And 0 < MyBase.AttributeCount
         Return baseRead
      End If
      
      'Read attribues;
      If _ReadAttributeValue Then
         _ReadAttributeValue = MyBase.ReadAttributeValue()
         If Not _ReadAttributeValue Then
            ' End of attribute.
' End element.
            _NodeType = XmlNodeType.EndElement
         Else
            _NodeType = XmlNodeType.None
         End If
         Return True
      End If
      
      _ReadAttributes = MyBase.MoveToNextAttribute()
      If _ReadAttributes Then
         _ReadAttributeValue = True
         _NodeType = XmlNodeType.Element
         _AttributeName = MyBase.Name
         Return True
      Else
         _ReadAttributeValue = False
         _NodeType = XmlNodeType.None
         _AttributeName = String.Empty
         Return Read()
      End If
   End Function
     
   
   Public Overrides ReadOnly Property NodeType() As XmlNodeType
      Get
         If XmlNodeType.None = _NodeType Then
            Return MyBase.NodeType
         End If
         
         Return _NodeType
      End Get
   End Property
      
   Public Overrides ReadOnly Property Value() As String
      Get
         If XmlNodeType.None = _NodeType Then
            Return MyBase.Value
         End If
         
         Return String.Empty
      End Get
   End Property
      
   Public Overrides ReadOnly Property Name() As String
      Get
         If XmlNodeType.None = _NodeType Then
            Return MyBase.Name
         End If
         
         Return _AttributeName
      End Get
   End Property
End Class 'AttrToElementReader
[C#]
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.XPath;

public class AttrToElementReader: XmlTextReader {    
    private bool         _ReadAttributes = false;
    private bool         _ReadAttributeValue = false;
    private string       _AttributeName = String.Empty;
    private XmlNodeType  _NodeType = XmlNodeType.None;
    
    public AttrToElementReader(String fileName) : base(fileName) {
        base.WhitespaceHandling = WhitespaceHandling.None;
        // Intentionally Empty.
    }

    public override bool Read() {
        if (!_ReadAttributes) {
            bool baseRead = base.Read();
            _ReadAttributes = (baseRead && XmlNodeType.Element == base.NodeType && 0 < base.AttributeCount);
            return baseRead;
        }

        // Reading attribues;
        if (_ReadAttributeValue) {
            _ReadAttributeValue = base.ReadAttributeValue();
            if (!_ReadAttributeValue) {
                // End of attribute.
// End element.
                _NodeType = XmlNodeType.EndElement;
            }
            else {
                _NodeType = XmlNodeType.None;
            }
            return true;
        }

        _ReadAttributes = base.MoveToNextAttribute();
        if (_ReadAttributes) {
            _ReadAttributeValue = true;
            _NodeType           = XmlNodeType.Element;
            _AttributeName      = base.Name;            
            return true;
        }
        else {
            _ReadAttributeValue = false;
            _NodeType           = XmlNodeType.None;
            _AttributeName      = String.Empty;
            return Read();
        }        
    }


    public override XmlNodeType NodeType {
        get {
            if (XmlNodeType.None == _NodeType) {
                return base.NodeType;
            }

            return _NodeType;
        }
    }

   public override String Value {
        get {
            if (XmlNodeType.None == _NodeType) {
                return base.Value;
            }

            return String.Empty;
        }
    }

   public override String Name {
        get {
            if (XmlNodeType.None == _NodeType) {
                return base.Name;
            }

            return _AttributeName;
        }
    }
 
}//AttrToElementReader

链接 XmlReaders

下面的示例显示一个称为 XmlReaderReader 的实现类,作为一个类,它被用于将 XmlReaders 链接起来,从而通过委托调用来提供一个读取器流。在创建筛选特定的输入的读取器时这很有用,并且对于对 XML 进行特定分析,它也是一个性能优良的解决方案。

从此 XmlReaderReader 派生的类可以将任何 XmlReader 当作输入。在下面的示例中,XmlCustomReader 重载 Read 方法并跳过 price 元素节点,从而将它们从流中移除。

[Visual Basic]
' This sample demonstrate the ability to chain XmlReaders together by
' implementing an XmlReaderReader class which aggregates any given
' XmlReader and then delegates the calls to it
Namespace Test
   Public Class MyApp
      Public Shared Sub Main()
         Dim reader As New XmlTextReader("books.xml")
         Dim customreader As New XmlCustomReader(reader)
         customreader.ReadandWrite()
      End Sub
      
      Class XmlCustomReader
         Inherits XmlReaderReader
         
         Public Sub New(reader As XmlTextReader)
            MyBase.New(reader)
         End Sub
         
         Public Overrides Function Read() As Boolean
            Dim result As Boolean
            result = MyBase.Read()
            Select Case MyBase.NodeType
               Case XmlNodeType.Element
                  If MyBase.Name.Equals("price") Then
                     MyBase.Skip()
                  End If
               Case Else
            End Select
            Return result
         End Function
         
         Public Sub ReadandWrite()
            ' Read each node in the tree.
            While Read()
               Select Case NodeType
                  Case XmlNodeType.Element
                     Console.Write(("<" + Name))
                     While MoveToNextAttribute()
                        Console.Write((" " + Name + "='" + Value + "'"))
                     End While
                     Console.Write(">")
                  Case XmlNodeType.Text
                     Console.Write(Value)
                  Case XmlNodeType.CDATA
                     Console.Write(Value)
                  Case XmlNodeType.ProcessingInstruction
                     Console.Write(("<?" + Name + " " + Value + "?>"))
                  Case XmlNodeType.Comment
                     Console.Write(("<!--" + Value + "-->"))
                  Case XmlNodeType.Document
                     Console.Write("<?xml version='1.0'?>")
                  Case XmlNodeType.Whitespace
                     Console.Write(Value)
                  Case XmlNodeType.SignificantWhitespace
                     Console.Write(Value)
                  Case XmlNodeType.EndElement
                     Console.Write(("</" + Name + ">"))
               End Select
            End While
         End Sub
      End Class
      
      Public Class XmlReaderReader
         Inherits XmlTextReader
         Private _Reader As XmlTextReader
         
         Public Sub New(reader As XmlTextReader)
            _Reader = reader
         End Sub
         
         ' XmlReader methods and properties.
         Public Overrides ReadOnly Property NodeType() As XmlNodeType
            Get
               Return _Reader.NodeType
            End Get
         End Property
         
         Public Overrides ReadOnly Property Name() As [String]
            Get
               Return _Reader.Name
            End Get
         End Property
         
         Public Overrides ReadOnly Property LocalName() As [String]
            Get
               Return _Reader.LocalName
            End Get
         End Property
         
         Public Overrides ReadOnly Property NamespaceURI() As [String]
            Get
               Return _Reader.NamespaceURI
            End Get
         End Property
         
         Public Overrides ReadOnly Property Prefix() As [String]
            Get
               Return _Reader.Prefix
            End Get
         End Property
         
         Public Overrides ReadOnly Property HasValue() As Boolean
            Get
               Return _Reader.HasValue
            End Get
         End Property
         
         Public Overrides ReadOnly Property Value() As String
            Get
               Return _Reader.Value
            End Get
         End Property
         
         Public Overrides ReadOnly Property Depth() As Integer
            Get
               Return _Reader.Depth
            End Get
         End Property
         
         Public Overrides ReadOnly Property BaseURI() As String
            Get
               Return _Reader.BaseURI
            End Get
         End Property
         
         Public Overrides ReadOnly Property IsEmptyElement() As Boolean
            Get
               Return _Reader.IsEmptyElement
            End Get
         End Property
         
         Public Overrides ReadOnly Property IsDefault() As Boolean
            Get
               Return _Reader.IsDefault
            End Get
         End Property
         
         Public Overrides ReadOnly Property QuoteChar() As Char
            Get
               Return _Reader.QuoteChar
            End Get
         End Property
         
         Public Overrides ReadOnly Property XmlSpace() As XmlSpace
            Get
               Return _Reader.XmlSpace
            End Get
         End Property
         
         
         Public Overrides ReadOnly Property XmlLang() As String
            Get
               Return _Reader.XmlLang
            End Get
         End Property
         
         Public Overrides ReadOnly Property AttributeCount() As Integer
            Get
               Return _Reader.AttributeCount
            End Get
         End Property
         
         Overloads Public Overrides Function GetAttribute(name As String) As String
            Return _Reader.GetAttribute(name)
         End Function
         
         Overloads Public Overrides Function GetAttribute(name As String, namespaceURI As String) As String
            Return _Reader.GetAttribute(name, namespaceURI)
         End Function
         
         Overloads Public Overrides Function GetAttribute(i As Integer) As String
            Return _Reader.GetAttribute(i)
         End Function
         
         Default Public Overrides Overloads ReadOnly Property Item(i As Integer) As String
            Get
               Return _Reader(i)
            End Get
         End Property
         
         Default Public Overrides Overloads ReadOnly Property Item(name As String) As String
            Get
               Return _Reader(name)
            End Get
         End Property
         
         Default Public Overrides Overloads ReadOnly Property Item(name As String, namespaceURI As String) As String
            Get
               Return _Reader(name, namespaceURI)
            End Get
         End Property
         
         Overloads Public Overrides Function MoveToAttribute(name As String) As Boolean
            Return _Reader.MoveToAttribute(name)
         End Function
         
         Overloads Public Overrides Function MoveToAttribute(name As String, ns As String) As Boolean
            Return _Reader.MoveToAttribute(name, ns)
         End Function
         
         Overloads Public Overrides Sub MoveToAttribute(i As Integer)
            _Reader.MoveToAttribute(i)
         End Sub
         
         Public Overrides Function MoveToFirstAttribute() As Boolean
            Return _Reader.MoveToFirstAttribute()
         End Function
         
         Public Overrides Function MoveToNextAttribute() As Boolean
            Return _Reader.MoveToNextAttribute()
         End Function
         
         Public Overrides Function MoveToElement() As Boolean
            Return _Reader.MoveToElement()
         End Function
         
         ' This is the only place that needs to be changed.
         Public Overrides Function Read() As Boolean
            Return _Reader.Read()
         End Function
         
         Public Overrides ReadOnly Property EOF() As Boolean
            Get
               Return _Reader.EOF
            End Get
         End Property
         
         Public Overrides Overloads Sub Close()
            _Reader.Close()
         End Sub
         
         Public Overrides ReadOnly Property ReadState() As ReadState
            Get
               Return _Reader.ReadState
            End Get
         End Property
         
         Public Overrides Function ReadString() As String
            Return _Reader.ReadString()
         End Function
         
         Public Overrides Function ReadInnerXml() As String
            Return _Reader.ReadInnerXml()
         End Function
         
         Public Overrides Function ReadOuterXml() As String
            Return _Reader.ReadOuterXml()
         End Function
         
         Public Overrides ReadOnly Property NameTable() As XmlNameTable
            Get
               Return _Reader.NameTable
            End Get
         End Property
         
         Public Overrides Function LookupNamespace(prefix As String) As String
            Return _Reader.LookupNamespace(prefix)
         End Function
         
         Public Overrides Overloads Sub ResolveEntity()
            _Reader.ResolveEntity()
         End Sub
         
         Public Overrides Function ReadAttributeValue() As Boolean
            Return _Reader.ReadAttributeValue()
         End Function
      End Class
   End Class
End Namespace
[C#]
using System;
using System.Xml;

// This sample demonstrate the ability to chain XmlReaders together by
// implementing an XmlReaderReader class which aggregates any given
// XmlReader and then delegates the calls to it.

namespace Test
{
    public class MyApp 
    {
        public static void Main()
      {
         XmlTextReader reader = new XmlTextReader("books.xml");
         XmlChainingReader customreader = new XmlChainingReader(reader);
         customreader.ReadandWrite();

      }

      class XmlChainingReader : XmlReaderReader
      {
          public XmlChainingReader (XmlReader reader) : base (reader)
         {}

         public override bool Read ()
         {
            bool result;
            result = base.Read();

            switch (base.NodeType)
            {
            case XmlNodeType.Element:
              if (base.Name.Equals("price"))
                 base.Skip();
            break;

            default:
               break;
            }
            return result;
         }
      
         public void ReadandWrite()
         {
            // Read each node in the tree.
            while (Read())
            {
               switch (NodeType)
               {
                 case XmlNodeType.Element:
                  Console.Write("<" + Name);
                  while (MoveToNextAttribute())
                    Console.Write(" " + Name + "='" + Value + "'");
                  Console.Write(">");
                  break;
                 case XmlNodeType.Text:
                  Console.Write(Value);
                  break;
                 case XmlNodeType.CDATA:
                  Console.Write(Value);
                  break;
                 case XmlNodeType.ProcessingInstruction:
                  Console.Write("<?" + Name + " " + Value + "?>");
                  break;
                 case XmlNodeType.Comment:
                  Console.Write("<!--" + Value + "-->");
                  break;
                 case XmlNodeType.Document:
                  Console.Write("<?xml version='1.0'?>");
                  break;
                 case XmlNodeType.Whitespace:
                  Console.Write(Value);
                  break;
                 case XmlNodeType.SignificantWhitespace:
                  Console.Write(Value);
                  break;
                 case XmlNodeType.EndElement:
                  Console.Write("</" + Name + ">");
                  break;
               }
            }
         }
      }

      public class XmlReaderReader : XmlReader
      {
        
         XmlReader _Reader;

         public XmlReaderReader (XmlReader reader )
         {
            _Reader = reader;
         }

         // XmlReader methods and properties.

         public override XmlNodeType NodeType
         {
            get { return _Reader.NodeType; }
         }

         public override String Name
         {
            get { return _Reader.Name; }            
         }

         public override String LocalName
         {
            get { return _Reader.LocalName; }            
         }

         public override String NamespaceURI
         {
            get { return _Reader.NamespaceURI; }            
         }

         public override String Prefix
         {
            get { return _Reader.Prefix; }            
         }


         public override bool HasValue 
         { 
            get { return _Reader.HasValue; }           
         }             

         public override string Value
         {
            get { return _Reader.Value; }            
         }

         public override int Depth
         {
            get { return _Reader.Depth; }            
         }

         public override string BaseURI
         {
            get { return _Reader.BaseURI; }            
         }

         public override bool IsEmptyElement
         {
            get { return _Reader.IsEmptyElement; }            
         }

         public override bool IsDefault
         {
            get { return _Reader.IsDefault; }            
         }

         public override char QuoteChar
         {
            get { return _Reader.QuoteChar; }            
         }

         public override XmlSpace XmlSpace
         {
            get { return _Reader.XmlSpace; }            
         }

         public override string XmlLang
         {
            get { return _Reader.XmlLang; }            
         }


         public override int AttributeCount
         {
            get { return _Reader.AttributeCount; }            
         }

         public override string GetAttribute(string name)
         {
            return _Reader.GetAttribute( name );
         }

         public override string GetAttribute(string name, string namespaceURI) 
         {
            return _Reader.GetAttribute( name, namespaceURI );
         }

         public override string GetAttribute(int i) 
         {
            return _Reader.GetAttribute( i );
         }

         public override string this [ int i ] 
         {             
            get { return _Reader[ i ]; }
         }
        
         public override string this [ string name ]
         { 
            get { return _Reader[ name ]; }
         }

         public override string this [ string name,string namespaceURI ] 
         { 
            get { return _Reader[ name, namespaceURI ]; }
         }
        
         public override bool MoveToAttribute(string name) 
         {
            return _Reader.MoveToAttribute( name );
         }

         public override bool MoveToAttribute(string name, string ns)
         {
            return _Reader.MoveToAttribute( name, ns );
         }

         public override void MoveToAttribute(int i)
         {
            _Reader.MoveToAttribute( i );
         }

         public override bool MoveToFirstAttribute()
         {
            return _Reader.MoveToFirstAttribute();
         }

         public override bool MoveToNextAttribute()
         {
            return _Reader.MoveToNextAttribute();
         }

         public override bool MoveToElement()
         {
            return _Reader.MoveToElement();
         }

         //
         // This is the only place that needs to be changed.
         //
         public override bool Read()
         {
            return _Reader.Read();
         }

         public override bool EOF 
         { 
            get { return _Reader.EOF; }
         }
        
         public override void Close() 
         {
            _Reader.Close();
         }

         public override ReadState ReadState
         { 
            get { return _Reader.ReadState; }
         }

         public override string ReadString()
         { 
            return _Reader.ReadString();
         }

         public override string ReadInnerXml()
         { 
            return _Reader.ReadInnerXml();
         }

         public override string ReadOuterXml()
         { 
            return _Reader.ReadOuterXml();
         }

         public override XmlNameTable NameTable 
         { 
            get { return _Reader.NameTable; }
         }
        
         public override string LookupNamespace(string prefix) 
         {
            return _Reader.LookupNamespace( prefix );
         }

         public override void ResolveEntity() 
         {
            _Reader.ResolveEntity();
         }

         public override bool ReadAttributeValue()
         {
            return _Reader.ReadAttributeValue();
         }
      }

   }

}

将 XmlReader 与 SAX 读取器比较

和 SAX 读取器一样,XmlReader 是一个只进只读游标。它提供了对输入的快速和非缓存的流式访问。它可以读取流或文档。它使用户可以提取数据,并跳过对应用程序没有意义的记录。较大的差异在于 SAX 模型是一个“推送”模型,其中分析器将事件推到应用程序,在每次读取了一个新节点时通知应用程序,而使用 XmlReader 的应用程序可以随意从读取器提取节点。这种提取模型的优点在于以下方面:

优点说明
状态管理推送模型要求内容处理程序生成非常复杂的状态机器。提取模型客户端通过自然的、由上而下的过程优化简化了状态管理。
多个输入流提取模型允许客户端汇合多个输入流。而要在推送模型中进行此操作是非常复杂的。
分层推送模型可以建立在提取模型的顶部。反之则不行。
避免多余的字符串复制数据通常被从分析器缓冲区读入字符串对象,然后字符串对象被推送到客户端缓冲区。提取模型使客户端能够提供给分析器一个可以将字符串直接写入的缓冲区。
有选择的处理推送模型通知客户端每个项,包括特性、处理指令和空白,而提取模型客户端可以跳过项,只处理那些对应用程序有意义的项。这使得可以生成效率极高的应用程序。而且,可以预先设置影响处理 XML 流的方式(例如正常化)的属性。有关跳过内容的更多信息,请参见用 XmlReader 跳过内容
posted @ 2006-11-21 14:23  疯一样的自由  阅读(3245)  评论(0编辑  收藏  举报