XML 读取器和编写器----从文件读取 XML
如何从文件读取 XML
此示例阐释如何使用 XmlTextReader 类从文件读取 XML。该类提供对 XML 进行直接分析和标记化,并实现 W3C 可扩展标记语言 (XML) 1.0 及 XML 中的命名空间规范。
[运行示例] | [查看源代码] |
XmlReader 类是提供 XML 分析的 API,XmlTextReader 是旨在处理字节流的实现。
通常情况下,如果您需要将 XML 作为原始数据进行访问,则可以使用 XmlTextReader,这样可不必避免 DOM 开销。省去对 DOM 的访问可使读取 XML 的速度加快。例如,XML 文档可能有一个标头节,用于传递该文档以便在其他地方进行处理。XmlTextReader 有不同的构造函数,以指定 XML 数据的位置。此示例从 books.xml 文件加载 XML,如下列代码所示。
XmlTextReader reader = new XmlTextReader ("books.xml"); |
||
C# | VB |
加载后,XmlTextReader 通过使用 Read 方法在 XML 数据中移动,按顺序从文档中检索下一个记录。如果不再有记录,则 Read 方法返回假。
while (reader.Read()) { // Do some work here on the data ... } |
||
C# | VB |
要处理 XML 数据,每个记录都有一个可从 NodeType 属性确定的节点类型。NodeType 枚举返回节点类型后,该示例将测试此节点类型,以查看该类型是元素类型还是文档类型。如果该节点是两种类型中的一种,则此示例将使用 Name 和 Value 属性处理该节点,以显示有关该节点的详细信息。Name 属性返回节点名(如元素和属性名),而 Value 属性返回当前节点(记录)的节点值(节点文本)。
while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: // The node is an Element Console.Write("<" + reader.Name); while (reader.MoveToNextAttribute()) // Read attributes Console.Write(" " + reader.Name + "='" + reader.Value + "'"); Console.Write(">"); break; case XmlNodeType.DocumentType: // The node is a DocumentType Console.WriteLine(NodeType + "<" + reader.Name + ">" + reader.Value); break; ... } } |
||
C# | VB |
返回的 XmlNodeType 取决于正在使用的 XmlReader 类。例如,XmlTextReader 类从不返回下列类型的 XmlNodeType:Document、DocumentFragment、Entity、EndEntity 和 Notation 节点。请参阅 .NET 框架类库,以获取有关每个 XmlReader 类所返回的 XmlNodeType 的详细信息。
为 XmlNodeType 指定的节点类型等效于 W3C DOM 节点类型,并且具有进行只进读取所要求的某些扩展类型。
XmlNodeType 枚举成员 | 说明 |
---|---|
Attribute | 属性。 示例 XML:id='123'。 Attribute 节点可以有下列子节点类型:Text 和 EntityReference。Attribute 节点看上去与任何其他节点类型的子节点不同;请注意,它并不是某个 Element 的子节点。 |
CDATA | CDATA 节。 示例 XML:<![CDATA[my escaped text]]> CDATA 节用于转义文本块,否则这些文本块将被识别为标记。CDATASection 节点不能有任何子节点。CDATASection 节点可作为 DocumentFragment、EntityReference 和 Element 节点的子级。 |
Comment | 注释。 示例 XML:<!-- my comment --> Comment 节点不能有任何子节点。Comment 节点可作为 Document、DocumentFragment、Element 和 EntityReference 节点的子级。 |
Document | 作为文档树的根的文档对象,可提供对整个 XML 文档的访问。 Document 节点可以有下列子节点类型:Element(最多有一个)、ProcessingInstruction、Comment 和 DocumentType。Document 节点不能作为任何节点类型的子级。 |
DocumentFragment | 文档片段。 DocumentFragment 节点将节点或子树与文档关联起来,而它实际上并不包含在该文档中。DocumentFragment 节点可以有下列子节点类型:Element、ProcessingInstruction、Comment、Text、CDATASection 和 EntityReference。DocumentFragment 节点不能作为任何节点类型的子级。 |
DocumentType | 文档类型声明,由 <!DOCTYPE> 标记表示。 示例 XML:<!DOCTYPE ...> DocumentType 节点可以有下列子节点类型:Notation 和 Entity。DocumentType 节点可作为 Document 节点的子级。 |
Element | 元素。 示例 XML:<Name> Element 节点可以有下列子节点类型:Element、Text、Comment、ProcessingInstruction、CDATA 和 EntityReference。Element 节点可作为 Document、DocumentFragment、EntityReference 和 Element 节点的子级。 |
EndElement | 当 XmlReader 到达元素的末尾时返回。 示例 XML:</foo> |
EndEntity | 由于调用 ResolveEntity 而使 XmlReader 到达实体替换的末尾时返回。 |
Entity | 实体声明。 示例 XML:<!ENTITY ...> Entity 节点可以有表示扩展实体(例如 Text 节点和 EntityReference 节点)的子节点。Entity 节点可作为 DocumentType 节点的子级。 |
EntityReference | 对实体的引用。 示例 XML:&foo; 它可应用于所有实体,包括字符实体引用。EntityReference 节点可以有下列子节点类型:Element、ProcessingInstruction、Comment、Text、CDATASection 和 EntityReference。EntityReference 节点可作为 Attribute、DocumentFragment、Element 和 EntityReference 节点的子级。 |
None | 如果未调用 Read 方法,则由 XmlReader 返回。 |
Notation | 文档类型声明中的表示法。 示例 XML:<!NOTATION ...> Notation 节点不能有任何子节点。Notation 节点可作为 DocumentType 节点的子级。 |
ProcessingInstruction | 处理指令 (PI)。 示例 XML:<?pi test?> PI 节点不能有任何子节点。PI 节点可作为 Document、DocumentFragment、Element 和 EntityReference 节点的子级。 |
SignificantWhitespace | 混合内容模型中标记之间的空白,或在 xml:space= "preserve" 范围内的空白。 |
Text | 元素的文本内容。Text 节点不能有任何子节点。Text 节点可作为 Attribute、DocumentFragment、Element 和 EntityReference 节点的子级。 |
Whitespace | 标记间的空白。 |
XmlDeclaration | XML 声明节点。 示例 XML:<?xml version='1.0'?> 它必须是文档中的第一个节点。它不能有子级。它是根节点的子级。它可以具有提供版本和编码信息的属性。 |
Depth 属性返回 XML 文档中当前节点的深度,它并在格式化数据时很有用。位于文档根级别的节点的深度为 0。将此深度信息与 Name 和 Value 属性相结合,您可以创建这样一个示例,该示例将根据节点类型和深度处理 XML 文件并格式化输出,并在读取时收集统计信息。下列示例代码显示如何使用 Format 方法完成此基本的格式化。要查看完整的示例代码,请参阅查看源文件。
private static void Format(XmlReader reader, String nodeType) { // Format the output Console.Write(reader.Depth + " "); Console.Write(reader.AttributeCount + " "); for (int i=0; i < reader.Depth; i++) { Console.Write('\t'); } Console.Write(reader.Prefix + nodeType + "<" + reader.Name + ">" + reader.Value); // Display the attributes values for the current node if (reader.HasAttributes) { Console.Write(" Attributes:"); for (int j=0; j < reader.AttributeCount; j++) { Console.Write(" [{0}] " + reader[j], j); } } Console.WriteLine(); } |
||
C# | VB |
以上示例代码使用 HasAttributes 属性测试元素节点是否有任何属性节点,然后使用节点索引运算符检索每个属性值。这类似于收集节点的属性。此外,以上代码示例使用 AttributeCount 属性返回当前节点的属性数。如果您关心的只是属性值而不是属性节点的其他属性(如属性的名称),则可以使用此方法。
注意:有关通过移到每个属性节点的方式来访问属性的其他方法,以及读取节点的名称和值的方法,请参阅如何从流读取 XML。
以下输出是使用 books.xml 文件运行该示例产生的结果。在此输出中,第一列是 Depth 属性,第二列是 AttributeCount 属性。
0 0 XmlDeclaration<xml>version='1.0' 0 0 Comment<> This file represents a fragment of a book store inventory database 0 0 Element<bookstore> 1 3 Element<book> Attributes: [0] autobiography [1] 1981 [2] 1-861003-11-0 2 0 Element<title> 3 0 Text<>The Autobiography of Benjamin Franklin 2 0 Element<author> 3 0 Element<first-name> 4 0 Text<>Benjamin 3 0 Element<last-name> 4 0 Text<>Franklin 2 0 Element<price> 3 0 Text<>8.99 1 3 Element<book> Attributes: [0] novel [1] 1967 [2] 0-201-63361-2 2 0 Element<title> 3 0 Text<>The Confidence Man 2 0 Element<author> 3 0 Element<first-name> 4 0 Text<>Herman 3 0 Element<last-name> 4 0 Text<>Melville 2 0 Element<price> 3 0 Text<>11.99 1 3 Element<book> Attributes: [0] philosophy [1] 1991 [2] 1-861001-57-6 2 0 Element<title> 3 0 Text<>The Gorgias 2 0 Element<author> 3 0 Element<name> 4 0 Text<>Plato 2 0 Element<price> 3 0 Text<>9.99 Statistics for books.xml file XmlDeclaration: 1 ProcessingInstruction: 0 DocumentType: 0 Comment: 1 Element: 18 Attribute: 9 Text: 11 Whitespace: 27
摘要
- XmlTextReader 提供对 XML 数据的快速、非缓存和只进的读取访问。
- XmlTextReader 实现 W3C 可扩展标记语言 (XML) 1.0 和 XML 中的命名空间规范。
- XmlTextReader 提供从文件、流或 TextReader 读取 XML 的构造函数。
- Read 方法将读取器作为一个节点按顺序移动。
- 对于元素节点,可通过使用索引运算符获取属性值。
- 属性可表示为当前节点的节点列表,并可通过 HasAttributes 属性查看它。
- Depth 属性报告当前节点的深度,可用于进行格式化。位于根级别的节点的深度为 0。