Java SAX与StAX

时间:2020-01-09 10:36:30  来源:igfitidea点击:

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则支持。