在NET框架的SystemXML名称空间中包含的XMLTextReader类不需要对系统资源要求很高就能从XML文件中快速读取数据使用XMLTextReader类能够从XML文件中读取数据并且将其转换为HTML格式在浏览器中输出
读本文之前读者需要了解一些基本知识XMLHTMLC#编程语言以及NET尤其是ASPNET框架的一些知识
微软公司的NET框架为开发者提供了许多开发的便利随着XML的重要性不断增长开发者们都期待着有一整套功能强大的XML工具被开发出来NET框架没有辜负我们的这番期望在SystemXML 名称空间中组织进了以下几个用于XML的类
XMLTextReader提供以快速单向无缓沖的方式存取XML数据(单向意味着你只能从前往后读取XML文件而不能逆向读取)
XMLValidatingReader与XMLTextReader类一起使用提供验证DTDXDR和XSD架构的能力
XMLDocument遵循WC文档对象模型规范的一级和二级标准实现XML数据随机的有缓存的存取一级水平包含了DOM的最基本的部分而二级水平增加多种改进包括增加了对名称空间和级连状图表(css)的支持
XMLTextWriter生成遵循 WC XML 规范的XML文件
本文主要讲述的是第一个类XMLTextReader这个类设计的目的就是从XML文件中快速的读取数据而对系统资源(主要包括内存和处理器时间)不做很高的要求在父级程序的控制下它通过每次只处理一个节点的方式对XML文件进行逐步操作实现这种工作过程在XML文件的每个节点中父级程序能决定该节点的类型它的属性和数据(如果有的话)以及其他有关该节点的信息基于这些信息父级程序可以选择是处理这个节点还是忽略该节点的信息以满足各种应用程序请求的需要这被称为抽取式(pull)处理模型因为父级程序发出请求并且从XML文件中抽取各个节点然后根据需要处理它或者是不处理它
我们可以把XMLTextReader类和XML简单应用程序接口即SAX相比后者是在编程人员中非常流行的另一种读取XML数据的技术XMLTextReader 和SAX有一点很相似它们都不需要占用很多的系统资源就能迅速的从XML文件读取数据但是与XMLTextReader的抽取式模型迥然不同SAX使用的是推入式模型XML处理器通过 事件告知主机应用程序哪些节点数据是可以获得那些不能获得根据需要主机程序则作出相应的反应或置之不理换句话说数据的传送方向是从SAX处理程序中推入到主机程序员们势必会在抽取式和推入式处理模型谁更有优势的问题上争论一番但是大家都不可否认的是两种模型都能很好的进行工作NET 框架不支持SAX但是你能使用现存的SAX工具 例如 MSXML分析器用于你的NET 程序
XMLTextReader 类有一些构造程序来适应各种各样的情况比如从一个已经存在的数据流或统一资源定位网址读取数据最常见的是你或许想从一个文件读取XML数据那么也就有一个相应的构造程序来为此服务这里有一个例子(我的所有代码例子都使用的是C#语言如果你喜欢使用VISUAL BASIC语言它们转换起来很容易)
XMLTextReader myReader;
myReader = New XMLTextReader(c:\data\salesXML)
创建一个称为Read()方法的循环这个方法的返回值总是为真
直到到达文件的底部时返回值才变为假换句话说 循环在文件的开始时启动并且读入所有的节点 一次读入一个节点 直到到达文件的结尾
While (myReaderRead()) {
// 在这里处理每个节点
}
每次成功调用Read()之后XMLTextReader实例化程序包含了目前节点(即刚刚从文件中读取的那个节点)的信息我们可以从XMLTextReader的成员中获得上述信息就像表格中描述的一样并通过NodeType属性判断出当前节点的类型在节点类型的基础上程序的代码可以读取节点数据检查它是否有属性到底是忽略它还是根据程序需要进行相应的操作和处理
当使用NodeType属性时理解节点怎么联系到XML单元是非常重要的例如 看下列 XML元素
<city>Chongqing</city>
XMLtextReader 把这个元素看作 个节点顺序如下
.<city>标签被读为类型 XMLNodeTypeElement 节点元素的名字city可从 XMLTextReader 的Name属性中获得
.文本数据Chongqing被读为类型为XMLNodeTypeText的节点数据Chongqing 可从XMLTextReader 的Value属性中取得
.</city>标签被读为类型为XMLNodeTypeEndElement 节点同样元素的名称city可从XMLTextReader的Name属性中获得
这是 种重要的节点类型其它的类型在NET的说明文档中有详细说明请大家参阅相关资料
如果XMLTextReader遇到一个错误 例如出现违反XML句法的情况它抛出一个SystemXMLXMLException类型的异常使用这个类的代码应该总是被保护 ( 在Try……Catch块中)就像你以后在演示程序中看到的一样
本文只是一篇相当简单的介绍XMLTextReader 类的文章XMLTextReader类有相当多的成员在这里不可能一一述及当读入XML数据时XMLTextReader能提供相当强的灵活性即便如此我仍然进行了大量的论述以保证读者能编制程序来实现现实世界中经常要求完成的任务也就是从一个XML文件读取数据然后以HTML的格式输出从而实现在浏览器中的显示
这个ASPNET程序(脚本)在服务器上运行并产生一个HTML页面返回浏览器这段脚本程序在代码段 给出它用来工作使用的 XML 数据文件在代码段 给出你能看到这个 XML 文件包含一份表示联系关系的列表程序的目标即是将这个列表显示出来为了更容易我们观察这些列表已经被格式化了
运行程序
. 将代码段存为XMLTextReaderASPx文件将代码段存为XMLDataXML文件
. 把这两个文件都放在一个已经安装好NET 框架的网络服务器的虚拟文件夹中
. 打开 Internet Explorer 并且浏览这个ASPx文件例如在一个局域网服务器上 URL 将是 localhost/xmltextreaderASPx
程序工作的大部分都由XMLDisplay 类来做尤其是被ProcessXML()方法完成的它每次读取一个节点XML数据对于感兴趣的元素节点数据和后跟冒号的节点名将和相应的HTML格式化标签一起写入输出结果中在这阶段输出结果由一个HTML文本暂时储存在其中的StringBuilder对象构成
ProcessXML()方法是从LoadDocument()方法调用的这个方法执行的任务是产生一个XMLTextReader实例化程序并在调用ProcessXML之前装载XML文件它同时也处理异常随后产生错误的信息并在浏览器中显示出来最终该方法返回一个字符串这个字符串或者包含产生的HTML内容或者如果异常发生的话就包含出错信息
程序执行以Page_Load()程序开始当浏览器请求浏览这个页面时这一步会自动执行这里的代码实例化了XMLDisplay 类并调用它的LoadDocument()方法如果一切运行正常的话格式化的HTML形式的返回值将被拷贝到页面的一个<div>标签中生成的HTML文档被送回到浏览器中并显示出来
其他的NET 框架的类比如XMLDocument类在读取XML数据方面表现如何呢XMLDocument 类与XMLTextReader 类不同它在存储器中创建整个XML文档的节点树这样就可以随机的获得XML数据(与XMLTextReader 类获得数据的线性方式正好相反)并且在修改XML文件的数据和结构时具有非常完美的灵活性另外XMLDocument允许执行XSLT 转变不过这些额外的功能是以运行速度的降低和系统资源的更多占用为代价的
代码段XmlTextReaderaspx
<%@ Import Namespace=SystemXml %>
<script language=C# runat=server>
public class XmlDisplay
file://这个类读入并处理XML文件
{
public string LoadDocument(String XmlFileName) {
XmlTextReader xmlReader = null;
StringBuilder html = new StringBuilder();
try {
file://创建XMLTextReader的实例
xmlReader = new XmlTextReader(XmlFileName);
// 处理XML文件
htmlAppend(ProcessXml(xmlReader));
}
catch (XmlException ex){
htmlAppend(发生一个XML异常 +
exToString());
}
catch (Exception ex){
htmlAppend(发生一个普通异常 +
exToString());
}
finally
{
if (xmlReader != null)
xmlReaderClose();
}
return htmlToString();
}
private string ProcessXml(XmlTextReader xmlReader)
{
StringBuilder temp = new StringBuilder();
file://这个方法读入XML文件并生成输出的HTML文档
while ( xmlReaderRead() )
{
// 处理一个元素节点的起始
if (xmlReaderNodeType == XmlNodeTypeElement)
{
file://忽略<people>和<person>元素
if ((xmlReaderName != person) && (xmlReaderName != people))
{
file://如果是一个<category>元素开始一个新的段落