• 2004-10-12

    XML与堆栈

    Tag:向上走

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://www.blogbus.com/dreamhead-logs/437969.html

    最近在研究XML解析,我的任务是将XML映射成内存对象。我知道你会告诉我有JAXB和Castor等等将XML绑定到对象的实现。那些技术是不错,而且可以用DTD或者Schema生成代码,省去大量的工作,但它们并不是我需要的,其根本原因在于效率。

    XML绑定技术生成的代码往往是针对XML本身的,而非我的应用。比如,在XML中有一项id,在我的应用中,它可能会代表不同的含义,而使用生成的代码无法展现出这一切,这样就会存在对解析之后的结果进行再次解析的可能。如果对效率没有什么要求,这是一件无关紧要的事情,比如对server端应用进行系统初始化,稍微慢一些无所谓,只要运行时效率高就可以了。当效率成为需求,这种做法就会成为心头之痛。

    几乎所有的XML解析基础无非是SAX和DOM两种,考虑到我的目标之一是不占用太多内存,所以,我的主攻方向是SAX。在JAXP大旗的笼罩之下,使用SAX进行XML解析的方式变得比较统一,加之其本身也相当简单,所以可以很快就可以了解API的基本用法。

    了解用法和实际写程序之间还是有一些差别。虽然之前,我对XML技术应用颇多,使用SAX进行解析XML文件,我还是第一次认真的思考。

    以下面的XML为例,
    <project name="sax">
        <member name="dreamhead"/>
    </project>
    SAX解析是一个顺序的流程,先解析project,然后是member。对应到我们的内存对象,解析出project,我们要创建一个Project对象,解析到member时,创建一个Member对象,还要将二者关联起来。说起来很容易,面对SAX API中的那些startElement、characters、endElement这些接口时,我着实有些不知所措。

    Kent Beck在《Test-Driven Development By Example》提出了一种在无所适从的情况下解决问题的方式——淋浴法。站在淋浴下确实会让人冷静下来,考虑到解析的顺序是prject开始、member开始、member结束、project结束,我想到了堆栈。不知是哪位先贤发掘了堆栈的思想,真想给他来个拥抱,同时,也为这个自认为匪夷所思的念头骄傲了一下。

    为了了解SAX在实际代码中的使用,我翻看了几个需要解析XML文件的开源代码。了解Commons Digester时,首先映入眼帘的便是——Stack。看来,开发经验尚浅的我能够想出的想法,多半已经有人想过,甚至广泛应用了。创新的前提是了解已有的东西,闭门造出来的多半是陈年旧货。

    既然已经有人创造我想要的东西,直接拿过来便是。于是,我决定直接使用Commons Digester。由于牵扯到reflection的使用,也许Commons Digester也会存在一些性能问题。按照Commons Digester的模式,将通用变成具体,那将是另外的故事了。

    分享到:

    历史上的今天:

    引用地址:

    评论

  • 我使用digester来解析namespace的过程中,出现了问题,能否举个digester解析namespace的例子?
  • 我觉得DOM方式解析才是用堆栈形式,SAX的解析好像就是类似流的方式,尽量减少资源消耗,解析到哪里,处理到哪里
    回复ctixx说:
    DOM给你的是解析的结果,SAX给你的是解析的过程,但二者并不矛盾。仔细体会一下,或许你就知道原来SAX用堆栈也是这么顺其自然。
    2004-10-14 19:33:07
  • XML本质上是一棵树,而遍历一棵树的方法,就是堆栈...这好像是数据结构的基本知识啊?

    同理,递归也无非就是堆栈而已
    回复曹晓钢说:
    你说得不错,或许这就是一个盲点吧!没人告诉我这么做,我也从来没有这么想过。

    文中我也说过,用堆栈的思想解析XML是别人已经想过的。不过,“发现”的感觉确实让人感觉兴奋。经历痛苦后的快乐是我们愿意为这场智力游戏之付出的源动力,不是吗?
    2004-10-14 19:30:22