新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论DOM, SAX, XPath等。
    [返回] 中文XML论坛 - 专业的XML技术讨论区XML.ORG.CN讨论区 - XML技术『 DOM/SAX/XPath 』 → [转帖]用SAX2.0处理XML大文档 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 4130 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: [转帖]用SAX2.0处理XML大文档 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     yinyufa 帅哥哟,离线,有人找我吗?
      
      
      等级:大一(高数修炼中)|大一(猛啃高等数学)
      文章:123
      积分:455
      门派:XML.ORG.CN
      注册:2004/2/16

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给yinyufa发送一个短消息 把yinyufa加入好友 查看yinyufa的个人资料 搜索yinyufa在『 DOM/SAX/XPath 』的所有贴子 引用回复这个贴子 回复这个贴子 查看yinyufa的博客楼主
    发贴心情 [转帖]用SAX2.0处理XML大文档

    Processing Large XML Documents Using SAX 2.0
    by W. Scott Means, coauthor of XML in a Nutshell

    翻译:wanghuzi  bestrong@263.net

    --------------------------------------------------------------------------------
      9 May 2001  

    最近我在讨论会和新闻组老听到的一个问题是,“我该怎么使用dom处理我的(在这里写一个很大的数字)兆大的xml文档?”不幸的,在大多数的案例中答案是“你不能这么做”。文档对象模型(以及其他把整个文档装入内存的解析方案)在处理大型文档时就会很困难。甚至在整个文档可以被装入内存的情况下,这么做也是不实用且效率不高的。

      

        
    Table of Contents
    Index
    Sample Chapter
    Author's Articles
    Full Description  

      
    确实,一些应用(例如xslt翻译处理)需要随机对每个元素进行访问。但是,那些处理小的局部的转换的小应用哪?或者那些只是想保存一部分特定元素到数据库表的数据库应用?或者只想统计一个xml文档的特性而没有实际操作的统计应用?有没有一个更简单的解决方案来处理这些应用?

    The Simple API for XML
    答案是绝对的“有“。(Simple API for XML )简单xml编程接口(一般叫做SAX)是一个容易实现,事件驱动的XML解析接口,它是由xml-dev邮件列表(由 Organization for the Advancement of Structured Information Standards来维护)的成员开发的。它被作为对上述的应用程序除了 W3C DOM 的另一个选择。不像DOM,SAX 不把XML文档整个解析并生成树状模型放入到内存中。而改为,根据XML文档结构给客户端应用发出事件通知。


    --------------------------------------------------------------------------------

    SAX的参考实现是由java写成的它位于 David Megginson's Web site。虽然它主要是一个基于java的技术,它也有用其他语言开发的版本,像perl,python,
    以及c++。微软的最新的实现整个SAX2.0的XML解析器(MSXML 3.0),可以由所有支持COM对象的语言使用。

    Note: SAX 1.0 vs. SAX 2.0
    SAX API 1.0和2.0之间变化非常大,很多1.0中的接口以及类在2.0中已经不建议使用了。同时又有几个类它们只是为了便于将1.0上的应用和解析器移植到sax2.0上。

    这篇文章只讨论在SAX2.0库上的开发,所以就不讨论那些属于SAX2.0,但不该被开发者使用在新应用中的类和接口。

    A Quick Overview of SAX
    SAX的参考实现不是一个全功能XML解析器。它是一组必须由想遵从它的解析器实现的java接口以及帮助类。下面的表格列举出了组成
    基本SAX的接口,类,以及例外:

    Package org.xml.sax
    Interfaces

    Attributes

    ContentHandler

    DTDHandler

    EntityResolver

    ErrorHandler

    Locator

    XMLFilter

    XMLReader

       
    Classes

    InputSource

       
    Exceptions

    SAXException

    SAXNotRecognizedException

    SAXNotSupportedException

    SAXParseException

    Package org.xml.sax.helpers
    Classes

    AttributesImpl

    DefaultHandler

    LocatorImpl

    ParserAdapter

    ParserFactory

    XMLFilterImpl

    XMLReaderFactory

    在这些中,最重要的和直接有用的是大量的Handler接口。ContentHandler接口中说明了所有的要传送信息的CALLBACK方法:

    文档的开始和结束
    XML元素的开始和结束
    元素名称域和属性
    名称域前缀映射范围
    处理指令
    字符数据和可忽略的空格
    ErrorHandler 接口被用来给客户端应用通报XML文档的语法或者有效性错误。如果一个应用程序没有注册一个错误处理器类,会发生不可预料的解析器行为。

    DTDHandler 接口是用来接受在文档DTD中的符号通知和没有解析的实体声明的。它不提供其它DTD结构,比如参数实体,元素声明,以及其他。


    --------------------------------------------------------------------------------

    Scott Means 还为oreilly.com写了其他两篇关于XML的文章,What's New in the DOM Level 2 Core? 和 Converting Unstructured Documents to XML。这些实用的文章介绍了W3C的DOM Level 2的推荐标准以及有关XML转换的实际例子。


    --------------------------------------------------------------------------------

    对一个实际用来解析文档和处理这些通知信息的应用类,它必须做到:

    实现一个或多个处理器(Handler)接口(ContentHandler, ErrorHandler, or DTDHandler)。  
    创建一个XMLReader类的实例,可能使用XMLReaderFactory helper class实现。
    在新的XMLReader实例中通过大量的set*Handler() 方法注册一个SAX-aware 类的实例
    调用XMLReader的parse()方法来处理文档。  
    现在,为了演示这些原则,让我们创建一个真正的可以通过SAX特性获得好处的应用。

    The Play's the Thing
    当我在互联网上为可以演示SAX的特性的应用程序寻找XML文档时,我找到了由Jon Bosak生成的XML文档格式的沙翁的剧本。下载ZIP文件的链接包括剧本,还有这个例子的源代码,在这篇文章的末尾都可以找到。

    这些剧本是使用下边的DTD来定义格式的。

    <!-- DTD for Shakespeare    J. Bosak    1994.03.01, 1997.01.02 -->
    <!-- Revised for case sensitivity 1997.09.10 -->
    <!-- Revised for XML 1.0 conformity 1998.01.27
         (thanks to Eve Maler) -->

    <!ENTITY amp "&">
    <!ELEMENT PLAY     (TITLE, FM, PERSONAE, SCNDESCR,
      PLAYSUBT, INDUCT?, PROLOGUE?, ACT+, EPILOGUE?)>
    <!ELEMENT TITLE    (#PCDATA)>
    <!ELEMENT FM       (P+)>
    <!ELEMENT P        (#PCDATA)>
    <!ELEMENT PERSONAE (TITLE, (PERSONA | PGROUP)+)>
    <!ELEMENT PGROUP   (PERSONA+, GRPDESCR)>
    <!ELEMENT PERSONA  (#PCDATA)>
    <!ELEMENT GRPDESCR (#PCDATA)>
    <!ELEMENT SCNDESCR (#PCDATA)>
    <!ELEMENT PLAYSUBT (#PCDATA)>
    <!ELEMENT INDUCT   (TITLE, SUBTITLE*,
      (SCENE+|(SPEECH|STAGEDIR|SUBHEAD)+))>
    <!ELEMENT ACT      (TITLE, SUBTITLE*, PROLOGUE?,
      SCENE+, EPILOGUE?)>
    <!ELEMENT SCENE    (TITLE, SUBTITLE*,
      (SPEECH | STAGEDIR | SUBHEAD)+)>
    <!ELEMENT PROLOGUE (TITLE, SUBTITLE*,
      (STAGEDIR | SPEECH)+)>
    <!ELEMENT EPILOGUE (TITLE, SUBTITLE*,
                    (STAGEDIR | SPEECH)+)>
    <!ELEMENT SPEECH   (SPEAKER+, (LINE | STAGEDIR | SUBHEAD)+)>
    <!ELEMENT SPEAKER  (#PCDATA)>
    <!ELEMENT LINE     (#PCDATA | STAGEDIR)*>
    <!ELEMENT STAGEDIR (#PCDATA)>
    <!ELEMENT SUBTITLE (#PCDATA)>
    <!ELEMENT SUBHEAD  (#PCDATA)>

    [编者提示:在这篇文章中,如果一行代码或者数据要分行,则第二行是缩进的]

    如果你像我一样(或者说你就是,你和我一样有同情心)你大概已经问你自己这样的问题了,“在《亨利六世》的第11幕中诺森伯兰郡伯爵到底说了多少句台词”(28句)或者,“在同一个剧目中Julius Caesar有多少段讲话”(39段)。好的,我承认在写这篇文章以前我也没有这么想过。但是因为从大型文档获取统计信息是SAX的主要应用,现在全世界都会知道在《温莎的风流妇人》中最长的台词有多长了(37句)。

    对剧本中的每段对话,以及对整个剧本,我想让我的应用程序来跟踪:

      

    DOM在处理大型文档时是非常笨拙的。

      
    台词的总句数
    台词段落的总数
    每个台词段落句数的平均数
    每段台词的最小和最大的句数
    剧本中每一幕的台词句数

    我还在输出的文档中包括了剧本的名字

    The PlayStats Program
    这个程序的实现可以在PlayStats.java 中找到(程序和例子在这里download here)。它是独立的而且包括main()方法,所以它可以通过命令行调用。程序的基本用法是这样的:

       java com.moonlightideas.examples.PlayStats.PlayStats play_url1.xml
                                    [play_url_2.xml ...]

    程序的基本流程是依次处理在命令行中的剧本文档。统计是累计的,而且当最后一个文档被处理完后结果被打印到标准输出(System.out),就像你猜的一样,是一个XML文档。

    Do-It-Yourself Data Structures
    写一个利用SAX从XML文档收集信息的程序需要一个好的思想和先期的设计。不像DOM,SAX不在你的内存中构造一个文档的副本。它会通知你文档的零零碎碎被认出来了,但是要靠你的程序来保存那些对你来说重要的信息。它同样需要使用它的程序知道源文挡的结构。在许多案例中,设想需要根据不同的元素之间的关系来确定。同样,因为对元素的开始标签,字符数据,以及结束标签的通知是分开的,所以通常需要将像属性值或者字符数据暂时保存起来,直到所有为彻底结束处理的数据都准备好为止。

    SAX的一个重要特性是,文档中对某一个特定的应用程序而言没有用的部分可以很容易的被忽略掉。这里我们的应用程序需要监听的元素是:

    <PLAY>
    <TITLE>
    <ACT>
    <SPEECH>
    <SPEAKER>
    <LINE>
      

    The Simple API for XML (better known as SAX) is a lightweight, event-driven XML parsing API that was developed by the members of the xml-dev mailing list.

      
    对所有这些元素而言,元素的嵌套并不重要。然而,《TITLE》元素可以作为大量的不同元素的孩子节点出现。因为我们只想保存剧本的名字,我们必须不仅仅识别《TITLE》标签,而且还要识别它的父亲节点。一个简单而灵活的解决方案是维持一个保存着现在元素嵌套层次的堆栈。每一次当startElement() 通知到达,当前的节点名被压入m_stackElements 堆栈。在endElement()方法处它被弹出。这种安排可以在处理过程中很方便的识别出一个元素的出身。


    Tracking Document Features
    因为是由SAX应用程序来存储以及跟踪文档信息,所以程序数据结构倾向于反映出要处理的XML文档的结构。例如,为了使收集每一个发言者所说台词句数的任务更简单独立,PlayStats类使用内部类Persona类。每一个单独的说话者(由<SPEAKER>标签来定义)被映射成一个Persona对象实例。就像上边的DTD所显示的那样,每一个<SPEECH>标签有一个或多个<SPEAKER>标签。handleSpeaker() 方法,当它在startElement()方法中被调用,设置m_sbChars类成员来指向一个新的StringBuffer 实例,所以说话者的名字会通过characters()方法被捕获。然后,在endElement()通知中名字可以被用来查询相应的persona记录(如果需要就创建一个新的)。


    --------------------------------------------------------------------------------

    为了跟踪最新的有关XML的技术,来访问O'Reilly Network的 XML.com.

    --------------------------------------------------------------------------------

    当<SPEECH>的结束标记被认出,handleSpeech()方法调用在现有的说话者列表中代表每一个说话者的persona对象的addSpeechLines()方法。它也被特殊的代表整个剧本统计的全局Persona对象实例调用(m_personTotal)。

    Outputting the Results
    当所有的剧本文档都被处理完成后,收集到的统计数据将被PlayStats.outputStats()方法输出到任意的输出流中。结果本身将用XML来表示。Persona对象的toString()方法返回一个用标准的XML表示的讲话者统计。当Persona对象用具体的例子说明的时候没有演讲者的名字,则<PERSONA>封闭标签被忽略。

    Wrapping Up
    SAX不是一个真正对每种XML应用都适用的解决办法。事实上,对所见即所得的XML编辑器,它显然不适用。但是,在一些适当的环境,它则是最好的(一些时候也是唯一的)高效率处理大量XML数据的方法。当要实现SAX应用的逻辑时理解已知文档的通知顺序是很关键的。我希望这篇文章以及相随的例子可以让你对SAX有一个最初的愉快认识。

    Links to Example Files:
    PlayStats.java program and examples
    Source code for the sample class and a few sample runs.
    The Plays of Shakespeare
    XML versions of the plays of Shakespeare, made available by Jon Bosak.

    --------------------------------------------------------------------------------

    W. Scott Means 从他17岁、1988年进入微软,是一名职业的软件开发者。他是OS/2 1.1以及Windows NT最初的开发者,他还在Advanced Technology and Business Development group中为Microsoft Network做了一些最初的工作。现在他是Enterprise Web Machines的CEO,南加州的一个对基础互连网进行投资的风险机构。

    --------------------------------------------------------------------------------

    O'Reilly & Associates recently released (January 2001) XML in a Nutshell.

    Sample Chapter 9, XPath, is available free online.

    You can also look at the Table of Contents, the Index, and the Full Description of the book.

    For more information, or to order the book, click here.

    Return to: xml.oreilly.com


       收藏   分享  
    顶(0)
      




    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2004/4/17 19:02:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 DOM/SAX/XPath 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/5/2 20:06:38

    本主题贴数1,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    62.500ms