Java SAX与StAX
SAX和StAX都是面向流/事件的XML解析器,但是它们的工作方式之间存在细微的差异。 SAX使用"推"模型,而StAX使用"推"模型。在不知不觉中,这可能会令人困惑。因此,在本文中,我将尝试更详细地解决这些模型之间的差异。
如果我们知道我在这里忘记的任何优点或者缺点,请随时给我发送电子邮件。我们可以在我的"关于"页面上找到有效的电子邮件地址。
SAX推模型
SAX推送模型意味着调用处理程序的是SAX解析器,而不是调用SAX解析器的处理程序。因此,SAX解析器将事件"推送"到处理程序中。总结如下:
SAX Parser --> Handler
使用推送模型,我们无法控制解析器对文件进行迭代的方式和时间。一旦启动了解析器,它将一直迭代直到结束,为输入XML文档中的每个XML事件调用处理程序。
StAX拉模型
StAX拉模型意味着调用解析器的是"处理程序"类,而不是相反。因此,处理程序类控制解析器何时将继续进行输入中的下一个事件。换句话说,处理程序将XML事件"拉出"解析器。此外,我们可以随时停止分析。拉模型总结如下:
Handler --> StAX Parser
优缺点摘要
与SAX推模型相比,StAX拉模型具有一些优势("控制反转"不是优势的少数情况之一)。我在下表中总结了SAX和StAX的正面和负面:
SAX + | SAX- | StAX + | StAX- |
+模式验证 | +可以进行细分/委派 +支持XML编写 | -无模式验证 |
StAX允许细分/委派
StAX相对于SAX的一大优势是,拉模型允许按方法和组件对XML输入进行子解析。那是什么意思
首先,这是一个XML示例:
<transportInfo> <driver>...</driver> <driver>...</driver> <vehicle>...</vehicle> <vehicle>...</vehicle> </transportInfo>
其次,看一下StAX StreamReader示例:
public void parse(){ XMLStreamReader streamReader = factory.createXMLStreamReader( new FileReader("data\test.xml")); while(streamReader.hasNext()){ streamReader.next(); if(streamReader.getEventType() == XMLStreamReader.START_ELEMENT){ String elementName = streamReader.getLocalName(); if("driver".equals(elementName)){ parseDriverAndAllChildren(streamReader); } else if("vehicle".equals(elementName)) { parseVehicleAndAllChildren(streamReader); } } } } public void parseDriverAndAllChildren(XMLStreamReader streamReader) { while(streamReader.hasNext()){ streamReader.next(); if(streamReader.getEventType() == XMLStreamReader.END_ELEMENT){ String elementName = streamReader.getLocalName(); if("driver".equals(elementName)){ return; } } else if(streamReader.getEventType() == XMLStreamReader.START_ELEMENT){ //do something to child elements... } } } public void parseVehicleAndAllChildren(XMLStreamReader streamReader) { while(streamReader.hasNext()){ streamReader.next(); if(streamReader.getEventType() == XMLStreamReader.END_ELEMENT){ String elementName = streamReader.getLocalName(); if("vehicle".equals(elementName)){ return; } } else if(streamReader.getEventType() == XMLStreamReader.START_ELEMENT){ //do something to child elements... } } }
注意,每个方法parseDriverAndAllChildren()和parseVehicleAndAllChildren()如何能够继续解析循环(while(streamReader.hasNext(){...}
并处理与" driver"相关的所有元素/他们各自感兴趣的"车辆"要素。
如果使用SAX处理程序执行此操作,则事情将变得很丑陋。我们将不得不在处理程序对象内设置一个标志,以告知我们所处的元素。将XML文档的子部分的解析和处理委派给方法或者组件是不可能的。没有上面显示的那么容易。
StAX支持XML编写
SAX不支持编写XML。如果我们不需要编写XML,那么这不是问题。如果确实需要编写XML,这可能会很烦人。我们将必须提出自己的XML编写机制。并不是说这很难,也不是什么。我们只需要这样做。在StAX中,已经内置了这样一个机制。
StAX不支持架构验证
据我所知,StAX不支持XML Schema验证,而SAX则支持。