SAX解析器如何工作?

时间:2019-01-31 23:06:01

标签: java xml dom sax

我是XML解析的新手。在执行一项需要解析Big XML文件的任务时。因此,在尝试制定一个好的解决方案时,我遇到了DOM和SAX这两个术语。两者都是两种不同类型的XML解析。我对SAX解析有点困惑。了解很多,但仍然感到困惑。

下面以XML为例

 <?xml version="1.0" encoding="UTF-8"?>
<note>
     <Desc>
       <to>Tove</to>
       <from>Jani</from>
       <heading>Reminder</heading>
       <body>Don't forget me this weekend!</body>
     </Desc>
     <Desc>
       <to>Tove</to>
       <from>Jani</from>
       <heading>Reminder</heading>
       <body>Don't forget me this weekend!</body>
     </Desc>
     <Desc>
       <to>Tove</to>
       <from>Jani</from>
       <heading>Reminder</heading>
       <body>Don't forget me this weekend!</body>
     </Desc>
</note>

让我们说,我只想全部读取所有<body>标签并将其写入文件。

我的疑问:

  1. 如果我使用DOM解析器执行此操作,它将首先将所有xml加载到内存中,然后查找<body>标记并写入文件吗?

  2. 如果我使用SAX解析器执行此操作,它将首先在磁盘上寻找<body>标签本身,一旦找到它,便开始从那里读取并继续加载到内存中,直到{{1 }}?

  3. 如果2个怀疑是正确的,那么这种阅读是如何发生的? SAX解析器是否逐字读取并将该字保留在内存中一段时间​​,并检查是否与代码正在寻找的标记匹配?因为标签的识别只能在内存中完成,但我认为这无处不在。并继续从内存中拉下单词,直到找到所选的匹配项或标记</body>。找到它的那一刻,它开始将所有单词保留在内存中,直到找到<body>

正确吗?
请纠正我..!

2 个答案:

答案 0 :(得分:2)

StAX(或拉解析器)将在您描述的用例中更好地工作。 DOM读取整个文档,SAX解析器生成您需要处理的事件,它们在内存中没有任何内容(内部消息除外)。使用SAX,您需要编写一个实现certain methods的内容处理程序,这还意味着您需要维护事件流的状态。例如,您发布的文档的第一块将生成以下(简化的)事件:

startDocument
startElement(note)
startElement(Desc)
startElement(to)
characters(Tove) // might come as multiple chunks
endElement(to)
...
endDocument

因此,如果标记名称为body,则需要签入startElement(如果只需要body中的note -> Desc个元素,则需要跟踪所有开始/结束元素)并设置一个标志。在characters中,如果该标志为true,则收集标签文本内容(或将其写入磁盘)。另外,在endElement中,该标志需要设置为false,以避免从其他标签中收集字符。

答案 1 :(得分:1)

DOM分析器将整个XML文档加载到内存中,并通过Java API使您可以使用它。这种方法的优点是易于使用和理解,但效率不高,因为:

  • 解析器必须读取整个XML文档并将其存储在内存中,即使您只想访问其中的一小部分。
  • DOM解析器使用的数据结构(最有可能是哈希映射)是通用的,并未针对您的情况进行优化。

SAX解析器较难使用,但性能可能更高。 SAX解析器不将任何内容存储在内存中。而是调用您提供的代码来处理遇到的每个XML元素。对于您的情况,它将回叫您说“我找到了!”。然后“我找到了!”等等。这些事件的处理方式取决于您,但是通常您将在内存中构建一些自定义Java对象,或者生成输出流。