如何使用多个 XmlReader
某些情况下,您可能使用一个读取器读取 XML 文档的一部分,使用一个或更多其他读取器读取该文档的其余部分。例如,一个电子商务订购系统可能有作为 XML 文档提交的订单。在处理这些订单时,一个读取器可处理文件开头部分的信息,然后将该文档的其余部分传送到另一个读取器,以处理剩余的订单细节。
为使读取器能够接受从其他读取器传来的文档,要使用两个 XmlTextReader 构造函数中的一个。一个构造函数获取字符串,另一个获取流。传递到该构造函数的字符串或流可以包含 XML 文档片段。这样,您就可以使一个读取器将已读取了部分信息的 XML 文档传递给另一个读取器。下列代码显示使用字符串或流的 XmlTextReader 构造函数的语法。
public XmlTextReader(String xmlFragment, XmlNodeType fragType, XmlParserContext context); public XmlTextReader(Stream xmlFragment, XmlNodeType fragType, XmlParserContext context); |
||
C# | VB |
XmlParserContext 对象为 XmlTextReader 提供适当的文档类型定义 (DTD)、外部资源的基本 URI、xml:lang、xml:space 以及命名空间信息。XmlParserContext 构造函数使用 8 个参数。如果第二个 XmlTextReader 仅要求命名空间/前缀查找,则可以指定 XmlNamespaceManager 和 XmlNameTable 参数并将空值传递给其他参数。
传递给构造函数的 XmlNamespaceManager 指定用于查找命名空间信息的命名空间管理器。例如,某文档片段可能包含在该文档前面部分定义的前缀。XmlNamespaceManager 使 XmlTextReader 可以正确解析文档中的任何前缀。当创建由 XmlTextReader 使用的 XmlNamespaceManager 时,必须使用 AddNamespace 方法将每个前缀和命名空间添加到集合中,XmlTextReader 将它们读到 XmlNamespaceManager 中。默认命名空间(如果存在)具有前缀 String.Empty。如果 XML 文档包含在 XmlNamespaceManager 中没有任何项的前缀,则 XmlTextReader 将引发 XmlException。
以编程方式从 XmlReader(及其派生类)中的节点检索前缀和命名空间时,只考虑读到 XML 文档中读取器的当前位置的节点。如果要将已读取了部分信息的流/字符串传递给另一个 XmlReader(使用 XmlParserContext),则不能考虑在流/字符串未读部分中定义的命名空间。较好的方法是在您预先知道命名空间的情况下使用 XmlNamespaceManager。
[运行示例] | [查看源代码] |
下列示例代码使用两个 XmlTextReader 读取 XML 文档并显示元素信息。第一个读取器读取该文档的第一部分,第二个读取器读取文档的剩余部分。此代码首先创建 XmlNamespaceManager,然后将在 XML 文档中使用的前缀和命名空间(包括默认命名空间)添加到 XmlNamespaceManager。接着,用于构造第二个 XmlTextReader 的 XmlParserContext 将此 XmlNamespaceManager 用作命名空间管理器,以用于查找命名空间信息。
//Create a new file stream for the specified source file. FileStream filestreamSource = new FileStream(args, FileMode.Open, FileAccess.Read); //Create a new reader with the file stream XmlTextReader reader = new XmlTextReader(filestreamSource); //Read the first part of the XML document while(reader.Read()) { //Display the elements and stop reading on the part1 endelement tag //then go to ReadPart2 to start another reader to read the rest of the file. switch(reader.NodeType) { case XmlNodeType.Element: Console.WriteLine("Name: {0}", reader.Name); Console.WriteLine(" Prefix: {0}", reader.Prefix); Console.WriteLine(" LocalName: {0}", reader.LocalName); Console.WriteLine(" Namespace: {0}", reader.NamespaceURI); break; case XmlNodeType.EndElement: //Stop reading at end element for element with localname equal to part1 if ("part1"==reader.LocalName) { Console.WriteLine("End reading part 1..."); Console.WriteLine(); goto ReadPart2; } break; } } //Read the rest of the XML document ReadPart2: Console.WriteLine("Begin reading part 2..."); //Create an XmlNamespaceManager and add the namespaces for the document. XmlNamespaceManager nsmanager = new XmlNamespaceManager(reader.NameTable); //Set default namespace--first param is null. nsmanager.AddNamespace(String.Empty, "http://tempuri.org/mydefaultnamespace"); nsmanager.AddNamespace("myns", "http://tempuri.org/mynamespace"); nsmanager.AddNamespace("yourns", "http://tempuri.org/yournamespace"); XmlParserContext pc = new XmlParserContext(reader.NameTable, nsmanager, reader.XmlLang, XmlSpace.Default); XmlTextReader reader2 = new XmlTextReader(filestreamSource, XmlNodeType.Element, pc); while(reader2.Read()) { switch (reader2.NodeType) { case XmlNodeType.Element: Console.WriteLine("Element Name: {0}", reader2.Name); Console.WriteLine(" Prefix: {0}", reader2.Prefix); Console.WriteLine(" LocalName: {0}", reader2.LocalName); Console.WriteLine(" Namespace: {0}", reader2.NamespaceURI); break; case XmlNodeType.EndElement: //Stop reading at end element for element with localname equal to part2 if ("part2"==reader2.LocalName) { Console.WriteLine("End reading part 2..."); goto Done; } break; } } Done: Console.WriteLine("Done."); reader.Close(); |
||
C# | VB |
摘要
- XmlTextReader 类派生自 XmlReader,可使用包含 XML 文档片段(如已由另一个 XmlReader 读取了部分信息的字符串或流)的字符串或流构造。
- XmlParserContext 类提供启动 XML 分析器所需的所有上下文信息,以在 XML 文档内的任何随机点启动它。这使 XmlTextReader 得以读取 XML 片段。