设为首页收藏本站language 语言切换
查看: 1113|回复: 0
收起左侧

利用微软的XML Parser创建XML文档

[复制链接]
发表于 2010-2-25 10:21:59 | 显示全部楼层 |阅读模式
<p >XML提供了不同或不相似的系统之间表达或交流信息的功能强大和灵活的方式。XML也是基于文本格式的,它在许多方面与HTML相似。例如,XML文档中也包含有开始(例如&lt;font&gt;)、结束(例如&lt;/font&gt;)标志。与HTML不同的是,我们可以在XML中使用任何喜欢的标志——使用多少标志或如何给它们命名都由我们自己来定。<p ><ccid_nobr><b>MXXMLWriter组件基础知识</b></ccid_nobr><p >创建XML文档的最大困难在于,XML文档应该符合一些基本的格式规则━━例如确保其中的元素不会重迭。尽管我们可以很容易地保证新的XML文档符合XML规格所定义的基本格式,但使用第三方的组件来管理它的输出会更加简单和安全。在本篇文章中我们将介绍的是MXXMLWriter,它是微软的MS XML Parser 3.0的一部分。<p >说起解析器,我们一般会想到在其输入端需要输入一些数据,然后在其输出端得到一系列的符号。微软的XML Parser与规则解析器的作用非常相似,它在输入端接受一个XML文档,然后在输出端生成一个XML文档对象模型(DOM)━━XML文档的一种基于对象的表达方式,或者生成一系列的Simple API for XML(SAX)事件。无论生成哪种输出格式,其输入都是XML文档。<p >MXXMLWriter是微软XML parser的一部分,对于通过编程方式创建XML文档非常有用。使用MXXMLWriter比自己动手创建XML文档有许多好处,其中包括:<p ><ccid_nobr><ul><li>MXXMLWriter产生的XML文档符合W3C XML 1.0 Namespace推荐标准,我们无需关心输出格式,因为解析器能够为我们解决这一切。</li><li>我们可以将MXXMLWriter的输出与SAX Content Handler绑定在一块儿,以较少的内存快速进行处理。</li><li>基于界面的编程模式使我们的代码更容易阅读和维护,我们可以将输出发送给一个支持IStream界面的String或COM对象。</li></ul></ccid_nobr><p ><ccid_nobr><b>处理XML文档的基础知识</b></ccid_nobr><p >在能够使用MXXMLWriter组件创建新的XML文档之前,我们需要了解一些处理XML文档的基本知识,因为MXXMLWriter希望使用它的应用程序能够成为SAX事件提供者。<p >处理XML文档有二种方式:使用文档对象模型(DOM)或者Simple API for XML(SAX)。二种方法在各种应用中各有优、缺点,DOM在XML文档查询方面有优势,SAX在快速处理超大型XML文档方面有优势,而且能够使我们完全控制解析的过程。<p ><ccid_nobr><b>使用DOM处理XML文档</b></ccid_nobr><p >当将XML文档加载至DOM中时,XML解析器会读取整个文档,在内存中创建许多表达这一文档的对象。下面的图1显示了一个简单的XML文档片段和DOM如何在内存中表示它:<p ><ccid_nobr><center><img  src="http://www.hh010.com/upload_files/article/244/9_cpwakx10890.gif"><br>点击小图放大,图1:DOM对象如何表达XML文档</center></ccid_nobr><p >图1显示,Document类的实例表示一个XML文档(图1中的第一部分),XML文档中包含有节点(图1中的第二部分),这些节点是DOM Node对象的实例。(图1中的第三部分)。<p >一旦DOM已经将全部XML文档读入内存,DOM就为你处理XML文档作好所有的准备了。我们可以通过使用循环重复处理其中的内容、使用XPath表达式查询特定的节点或随机访问DOM树的任意部分对DOM中的元素进行操作。关健是我们的应用程序能够对XML文档进行完整的控制,可以从文档在内存中的表示中提取所需要的信息。<p ><ccid_nobr><b>使用SAX处理XML文档</b></ccid_nobr><p >SAX编程模式与DOM编程模式完全不同。通过让应用程序截获XML解析器在处理XML文档时产生的事件,SAX可以使应用程序更接近XML解析器。由于事件是被推送到应用程序中的,因此,它提供的是一种“推”编程模式,应用程序无需象在使用DOM时那样作为一个控制点。<p ><ccid_nobr><center><img  src="http://www.hh010.com/upload_files/article/244/9_89gwm610891.gif"><br>点击小图放大,图2:使用SAX处理XML文档</center></ccid_nobr><p >图2显示,XML Reader(图2中的第一部分)负责读取XML文档。XML Reader请求了我们提供的一个组件,它在读取XML文档时调用了其界面中的方法。(图2中的第二部分)我们的应用程序(图2中的第三部分)则使用组件的输出。<p >在图2中,一个包含有ISAXXMLReader的组件被用作XML Reader。要使用SAX处理XML文档,需要在ISAXContentHandler界面中注册一个组件。当XML <p >Reader遇到文档中的元素时,它调用ISAXContentHandler方法处理startDocument、startElement等元素和提供有关XML <p >Reader读取的元素信息的字符。图3显示了一个事件的序列,该事件序列是XML Reader在处理样例文件(图1、2中出现的)时生成的。<p ><ccid_nobr><center><img  src="http://www.hh010.com/upload_files/article/244/9_0ps7fx10892.gif"><br>点击小图放大,图3:处理XML文档时的事件序列</center></ccid_nobr><p ><ccid_nobr><b>使用MXXMLWriter创建XML文档</b></ccid_nobr><p >MXXMLWriter是SAX的消费者,意味着使用MXXMLWriter的应用程序是SAX的提供者,MXXMLWriter使用SAX事件编写出正确格式的XML文档。<p >本篇文章中的例子代码是一个能够读取以“,”分割的文件并产生XML文档的控制台应用程序,它产生的XML文档显示在屏幕上,我们可以将其输出捕捉到文本文件中,并保存在磁盘上。例子代码使用STL(标准模板库)对文件的读取进行管理。下面的表1显示了MXXMLWriter的具体代码,它能够建立指向ISAXContentHandler等界面的指针:<p ><ccid_nobr><table width="580" border="1" cellspacing="0" cellpadding="0" bordercolorlight="black" bordercolordark="#ffffff"><tr><td bgcolor="e6e6e6" class="code">Listing 1 - Instanciating MXXMLWriter// MSXML2::IMXWriterPtr是一个智能化指针<br>MSXML2::IMXWriterPtr pXMLWriter;<br>pXMLWriter.CreateInstance(__uuidof(MSXML2::MXXMLWriter));<br>// ISAXContentHandler是一个由MXXMLWriter使用的界面<br>MSXML2::ISAXContentHandlerPtr pContentHandler;<br>pContentHandler=pXMLWriter; //calls QI for ISAXContentHandler on pXMLWriter<br>//ISAXErrorHandler是一个由MXXMLWriter使用的界面<br>MSXML2::ISAXErrorHandlerPtr pErrorHandler;<br>pErrorHandler=pXMLWriter; //calls QI for ISAXErrorHandler on pXMLWriter<br>// ISAXDTDHandler也是由MXXMLWriter使用的界面<br>MSXML2::ISAXDTDHandlerPtr pDTDHandler;<br>pDTDHandler=pXMLWriter; //calls QI for ISAXDTDHandler on pXMLWriter<br>//将输出内容输出到一个字符串中<br>pXMLWriter-&gt;put_output(CComVariant(L&quot;&quot;));</td></tr></table></ccid_nobr><p >一旦MXXMLWriter完成了,程序就会读取文本文件,并生成供MXXMLWriter处理的SAX事件。程序如下面的表2所示:<p >表2:生成供MXXMLWriter使用的事件<p ><ccid_nobr><table width="580" border="1" cellspacing="0" cellpadding="0" bordercolorlight="black" bordercolordark="#ffffff"><tr><td bgcolor="e6e6e6" class="code">std::getline(fileIn,lineFromFile);<br>while(fileIn.good())<br>{<br>npos=lineFromFile.find_first_of(&quot;,&quot;,nlast);<br>//确定当前行有一个“,”号;<br>//如果没有发现,find_first_of返回std::wstring::npos<br>if(npos!=std::wstring::npos){<br>wElementName=A2W(lineFromFile.substr(nlast,npos-nlast).c_str());<br>// startElement元素<br>pContentHandler-&gt;startElement(L&quot;&quot;,0,L&quot;&quot;,0,<br>const_cast&lt;wchar_t*&gt;(wElementName.c_str()),<br>wElementName.length(),NULL);<br>nlast= ++npos;<br>// 获取当前行的其他部分(元素值)<br>wElementValue=A2W(lineFromFile.substr(nlast).c_str());<br>// 字符<br>pContentHandler-&gt;characters(<br>const_cast&lt;wchar_t*&gt;(wElementValue.c_str()),<br>wElementValue.length());<br>// endElement元素<br>pContentHandler-&gt;endElement(L&quot;&quot;,0,L&quot;&quot;,0,<br>const_cast(wElementName.c_str()),<br>wElementName.length());<br>}<br>std::getline(fileIn,lineFromFile);<br>nlast=0;<br>}</td></tr></table></ccid_nobr><p >上面的程序置于一个由输入文件的状态控制的循环中,它使用std::getline(...)方法逐行读取输入文件,并将读取的行存储在std::string类型变量lineFromFile中。MXXMLWriter期望的输入数据类型为Unicode字符串,程序使用ANSI字符串使文档的解析更简单。这样,程序在把从文件中读取的ANSI字符串在传递给MXXMLWriter之前才转换为Unicode字符串。<p >输入文件是文本文件,每行中包括一个元素和元素值对儿。程序代码能够对由元素和元素值对组成的XML文档进行处理。<p >表3:样例文本文件<p ><ccid_nobr><table width="580" border="1" cellspacing="0" cellpadding="0" bordercolorlight="black" bordercolordark="#ffffff"><tr><td bgcolor="e6e6e6" class="code">author, Essam Ahmed<br>topic, Using the Microsoft XML Parser...<br>author, Essam Ahmed<br>topic, Using the Microsoft XML Parser...<br>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-16&quot; standalone=&quot;no&quot;?&gt;<br>&lt;RootElement&gt;<br>&lt;author&gt;Essam Ahmed&lt;/author&gt;<br>&lt;topic&gt;Using the Microsoft XML Parser...&lt;/topic&gt;<br>&lt;/ RootElement&gt;</td></tr></table></ccid_nobr><p >程序把其输出内容输出到屏幕上,如果想把输出保存在文件中,可以使用重定向符&gt;将输出内容输出到一个文件中。<p ><ccid_nobr><b>结束语</b></ccid_nobr><p >这篇文章介绍了如何使用Microsoft XML 3.0 Parser中的一个组件—MXXMLWriter来创建XML文档。使用MXXMLWriter比自己编写类似的代码有几点好处,它不但符合现有的标准,而且在标准改变时也无需升级自己的代码。<p >(责任编辑 <ccid_nobr>尤北</ccid_nobr>)                                 <p align="center"></p></p>
您需要登录后才可以回帖 登录 | 论坛注册

本版积分规则

QQ|Archiver|手机版|小黑屋|sitemap|鸿鹄论坛 ( 京ICP备14027439号 )  

GMT+8, 2025-4-10 15:16 , Processed in 0.059128 second(s), 22 queries , Redis On.  

  Powered by Discuz!

  © 2001-2025 HH010.COM

快速回复 返回顶部 返回列表