StAX---基于事件的拉式XML解析

指针极昼
• 阅读 3200

简介

StAX,全称Streaming API for XML,一种全新的,基于流的JAVA XML解析标准类库。其最终版本于 2004 年 3 月发布,并成为了 JAXP 1.4(将包含在即将发布的 Java 6 中)的一部分。在某种程度上来说,StAX与SAX一样是基于XML事件的解析方式,它们都不会一次性加载整个XML文件。但是它们之间也有很大的不同。

<!--more-->

与SAX相比

虽然StAX与SAX一样基于XML事件解析,相比于DOM将整个XML加载进内存来说效率高。不同的是,StAX在在处理XML事件的方式上使得应用程序更接近底层,所以在效率上比SAX更优秀。

使用SAX时,我们知道XML事件是由解析器调用开发人员编写的回调方法来处理的,也就是说应用程序是被动于解析器的。应用程序只能被动的等待解析器将XML事件推送给自己处理,对于每一种事件都需要在解析开始之前就做好准备。这种方式被称为‘推(push)‘。
而StAX正好相反,StAX采用一种‘拉(pull)‘的方式,由应用程序主动从解析器中获取当前XML事件然后更具需求处理(保存或者忽略)。StAX使得应用程序掌握了主动权,可以简化调用代码来准确地处理它预期的内容,或者发生意外时停止解析。此外,由于该方法不基于处理程序回调,应用程序不需要像使用 SAX 那样模拟解析器的状态。

简单入门

获取解析器工厂
与其他解析技术一样,在使用StAX解析器之前也需要获取其工厂类。

import java.io.InputStream;  
import java.io.OutputStream;  
import javax.xml.stream.XMLInputFactory;  
import javax.xml.stream.XMLOutputFactory;  
  
  
public class StAX_Frist {  
 public void writeXMlByStream(OutputStream out){  
     XMLOutputFactory outFactor=XMLOutputFactory.newInstance();//写解析器工厂  
     .......  
 }  
    public void  readXmlByStream(InputStream in){  
          
        XMLInputFactory inFactory=XMLInputFactory.newInstance();//读解析器工厂  
        .......  
    } 

主要API

StAX 实际上包括两套处理 XML 的 API,分别提供了不同程度的抽象。基于指针(Cursor)的 API 允许应用程序把 XML 作为一个标记(或事件)流来处理。在这里,解析器就像一跟指针一样在文件流上前进,应用程序可以跟随解析器从文件的开头一直处理到结尾。这是一种低层 API,尽管效率高,但是没有提供底层 XML 结构的抽象。Cursor API 由两个主要API组成,XMLStreamReader和XMLStreamWriter,分别由XMLInputStreamFactory和XMLOutputStreamFactory获取。
使用Cursor API 读XML文件:

import java.io.InputStream;  
import javax.xml.stream.XMLInputFactory;;  
import javax.xml.stream.XMLStreamConstants;  
import javax.xml.stream.XMLStreamReader;  
  
  
public class StAX_Frist {  
      
    public void  readXmlByStream(InputStream in){  
          
        XMLInputFactory inFactory=XMLInputFactory.newInstance();//读解析器工厂  
          
  
        try {  
            XMLStreamReader reader=inFactory.createXMLStreamReader(in);//获取读解析器  
            while(reader.hasNext()){//reader.hasNext();说明文件未到结尾。  
                int eventId=reader.next();  
                switch (eventId) {  
                case XMLStreamConstants.START_DOCUMENT:  
                    System.out.println("start docmuent");  
                    break;  
                      
                case XMLStreamConstants.START_ELEMENT:  
                    System.out.println("<"+reader.getLocalName()+">");  
                    for(int i=0;i<reader.getAttributeCount();i++){  
                        System.out.println(reader.getAttributeLocalName(i)+"="+reader.getAttributeValue(i));  
                    }  
                    break;  
                      
                case XMLStreamConstants.CHARACTERS:  
                    if(reader.isWhiteSpace()){  
                        break;  
                    }  
                    System.out.println(reader.getText());  
                    break;  
                case XMLStreamConstants.END_ELEMENT:  
                    System.out.println("</"+reader.getLocalName()+">");  
                      
                    break;  
                case XMLStreamConstants.END_DOCUMENT:  
                    System.out.println("end docmuent");  
                    break;  
                default:  
                    break;  
                }  
            }  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  

另外一种是较为高级的基于迭代器(Iterator)的 API ,它允许应用程序把 XML 作为一系列事件对象来处理,每个对象和应用程序交换 XML 结构的一部分。应用程序只需要确定解析事件的类型,将其转换成对应的具体类型,然后利用其方法获得属于该事件的信息。基于事件迭代器的方法具有一个基于指针的方法不具备的重要优点。通过将解析器事件变成一级对象,从而让应用程序可以采用面向对象的方式处理它们。这样做有助于模块化和不同应用程序组件之间的代码重用。Iterator API 由两个主要API组成,XMLEventReader和XMLEventWriter,分别由XMLInputStreamFactory和XMLOutputStreamFactory获取。
使用Iterator API 读XML文件:


import java.io.InputStream;  
import java.util.Iterator;  
import javax.xml.stream.XMLEventReader;  
import javax.xml.stream.XMLInputFactory;  
import javax.xml.stream.XMLStreamConstants;  
import javax.xml.stream.events.Attribute;  
import javax.xml.stream.events.Characters;  
import javax.xml.stream.events.StartElement;  
import javax.xml.stream.events.XMLEvent;  
  
   public class StAX_Frist {  
      
           public void  readXmlByEvent(InputStream in){  
          
        XMLInputFactory factory=XMLInputFactory.newInstance();//获取解析器工厂  
        try {  
            XMLEventReader reader=factory.createXMLEventReader(in);//获取解析器  
            while(reader.hasNext()){  
            XMLEvent event=reader.nextEvent();  
              
                switch (event.getEventType()) {  
                case XMLStreamConstants.START_DOCUMENT:  
                    System.out.println("start docmuent");  
                    break;  
                      
                case XMLStreamConstants.START_ELEMENT:  
                    StartElement element=(StartElement)event;  
                    System.out.println("<"+element.getName().getLocalPart()+">");  
                    for(Iterator it=element.getAttributes();it.hasNext();){  
                        Attribute attr=(Attribute) it.next();  
                        System.out.println(attr.getName().getLocalPart()+"="+attr.getValue());  
                    }  
                    break;  
                      
                case XMLStreamConstants.CHARACTERS:  
                    Characters charData=(Characters)event;  
                    if(charData.isIgnorableWhiteSpace()&&charData.isWhiteSpace()){  
                        break;  
                    }  
                    System.out.println(charData.getData());  
                    break;  
                case XMLStreamConstants.END_ELEMENT:  
                    element=(StartElement)event;  
                    System.out.println("</"+element.getName().getLocalPart()+">");  
                      
                    break;  
                case XMLStreamConstants.END_DOCUMENT:  
                    System.out.println("end docmuent");  
                    break;  
                default:  
                    break;  
                }  
            }  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Stella981 Stella981
3年前
Apache Synapse 远程代码执行漏洞(CVE
!(https://oscimg.oschina.net/oscnet/435fc4cde65d4aee9a2efca3080cb89e.png)0x00事件背景ApacheSynapse是一个简单、轻量级的高性能企业服务总线(ESB),它是在ApacheSoftwareFoun
Wesley13 Wesley13
3年前
Java8系列之Stream总结
流的简介  官方解释,Stream是Java8的一大亮点,它与java.io包里的InputStream和OutputStream是完全不同的概念。它也不同于StAX对XML的解析的Stream,也不是AmazonKinesis对大数据实时处理的Stream。它是对集合对象功能的增强,她专注于对集合对象进行各种非常便利、高效的聚合操作(ag
Stella981 Stella981
3年前
Kerberos无约束委派的攻击和防御
 0x00前言简介当ActiveDirectory首次与Windows2000Server一起发布时,Microsoft就提供了一种简单的机制来支持用户通过Kerberos对Web服务器进行身份验证并需要授权用户更新后端数据库服务器上的记录的方案。这通常被称为Kerberosdoublehopissue(双跃点问题),
Wesley13 Wesley13
3年前
VBox 启动虚拟机失败
在Vbox(5.0.8版本)启动Ubuntu的虚拟机时,遇到错误信息:NtCreateFile(\\Device\\VBoxDrvStub)failed:0xc000000034STATUS\_OBJECT\_NAME\_NOT\_FOUND(0retries) (rc101)Makesurethekern
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
3年前
Android开发之使用pull解析XML文件
Android已经集成进了Pull解析器,所以无需添加任何jar文件。android系统本身使用到的各种xml文件,其内部也是采用Pull解析器进行解析的。Pull解析器的运行方式与SAX解析器相似。它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。跟SAX不同的是,Pull解析器产生的事
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
Android xml (sax)
1、什么事SAXSAX,全程是SimpleApiforXLM,即是指一种接口,也是指一个软件包。作为接口,SAX是事件驱动型XML解析的一个标准接口2、SAX基本原理3、SAX常用接口4、SAX解析SAX的原理SAX的工作原理简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、yuansu(eleme
Stella981 Stella981
3年前
Noark入门之异步事件
引入异步事件主要是为了各模块的解耦,每当完成一个动作时,向系统发布一个事件,由关心的模块自己监听处理,可选择同步处理,异步处理,延迟处理。何时发布事件,当其他模块关心此动作时<br比如获得道具时,任务系统模块要判定完成进度,BI模块需要上报等等都可以监听此事件,已达模块解耦0x00事件源一个实现xyz.noark.core.event