Java SAX解析器是如何工作的?
我不熟悉XML解析。在执行一项需要解析大XML文件的任务时。因此,在尝试制作一个好的解决方案时,我遇到了这两个术语,DOM和SAX。这两种都是两种不同类型的XML解析。我在这里对SAX解析有点困惑。读了很多,但仍然感到困惑 让我们以下面的XML为例Java SAX解析器是如何工作的?,java,xml,dom,sax,Java,Xml,Dom,Sax,我不熟悉XML解析。在执行一项需要解析大XML文件的任务时。因此,在尝试制作一个好的解决方案时,我遇到了这两个术语,DOM和SAX。这两种都是两种不同类型的XML解析。我在这里对SAX解析有点困惑。读了很多,但仍然感到困惑 让我们以下面的XML为例 <?xml version="1.0" encoding="UTF-8"?> <note> <Desc> <to>Tove</to> <from
<?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>
托弗
贾尼
提醒
这个周末别忘了我!
托弗
贾尼
提醒
这个周末别忘了我!
托弗
贾尼
提醒
这个周末别忘了我!
比方说,我只想让所有人都读所有的
标记并写入文件
我的疑问是:
标记并写入文件吗
标记本身,并在找到标记的那一刻开始读取,并一直加载到内存中,直到
请纠正我 StAX(或pull解析器)将更好地适用于您描述的用例。 DOM读取整个文档,SAX解析器生成您需要处理的事件,它们不在内存中存储任何内容(内部除外)。使用SAX,您需要使用实现一个内容处理程序,这也意味着您需要维护事件流的状态。例如,您发布的文档的第一个区块将生成以下(简化)事件: 因此,如果标记名为
body
(如果只需要note->Desc
中的body
元素,则需要在startElement中进行检查,并设置标志。在characters
中,如果标志为true,则收集标记文本内容(或将其写入磁盘)。此外,在endElement
中,需要将标志设置为false,以避免从其他标记收集字符。StAX(或pull解析器)将更好地适用于您描述的用例。
DOM读取整个文档,SAX解析器生成您需要处理的事件,它们不在内存中存储任何内容(内部除外)。使用SAX,您需要使用实现一个内容处理程序,这也意味着您需要维护事件流的状态。例如,您发布的文档的第一个区块将生成以下(简化)事件:
因此,如果标记名为
body
(如果只需要note->Desc
中的body
元素,则需要在startElement中进行检查,并设置标志。在characters
中,如果标志为true,则收集标记文本内容(或将其写入磁盘)。此外,在endElement
中,需要将标志设置为false,以避免从其他标记收集字符。DOM解析器将整个XML文档加载到内存中,并通过Java API使其可用。这种方法的优点是易于使用和理解,但效率不高,因为:
- 解析器必须读取整个XML文档并将其存储在内存中,即使您只想访问其中的一小部分
- DOM解析器使用的数据结构(最有可能是哈希映射)是通用的,并且没有针对您的情况进行优化
SAX解析器更难使用,但它的性能可能更高。SAX解析器在内存中不存储任何内容;相反,它调用您提供的代码来处理遇到的每个XML元素。在您的情况下,它会给您回电话说“我找到了!”然后说“我找到了!”等等。您如何处理这些事件取决于您,但通常您要么在内存中构建一些自定义Java对象,要么生成一个输出流。DOM解析器将整个XML文档加载到内存中,并通过Java API将其提供给您。这种方法的优点是易于使用和理解,但效率不高,因为:
- 解析器必须读取整个XML文档并将其存储在内存中,即使您只想访问其中的一小部分
- DOM解析器使用的数据结构(最有可能是哈希映射)是通用的,并且没有针对您的情况进行优化
SAX解析器更难使用,但它的性能可能更高。SAX解析器在内存中不存储任何内容;相反,它调用您提供的代码来处理遇到的每个XML元素。在您的情况下,它会给您回电话说“我找到了!”然后是“我找到了!”等等。您如何处理这些事件取决于您,但通常您会在内存中构建一些自定义Java对象,或者生成一个输出流。当您说“我找到了”时,它会给您回电话说“我找到了!”!“然后”我发现了!,它在哪里求值?解析时,将从磁盘进行读取,并且它必须求值“我找到了”“内存中的某些内容本身..不是吗?假设您正在从磁盘读取,是的,XML将在磁盘上,回调将在内存中。”。但是SAX解析器将只在内存中保留当前正在读取的元素的相关信息。一旦它将该信息传递给您的程序,解析器就会忘记它。(好的,它必须在内存中保留一些额外的信息,以便跟踪它在文档中的位置,但开销很小。)这样考虑。
startDocument
startElement(note)
startElement(Desc)
startElement(to)
characters(Tove) // might come as multiple chunks
endElement(to)
...
endDocument