XML学习05-Java中SAX方式解析XML文件

一、什么是SAX方式

-SAX: Simple API for XML。属于开源社区XML-DEV,几乎所有的XML解析器都支持它。
-相比于DOM方式,SAX方式更为迅速,占用内存资源更少。

二、Java中使用SAX方式解析XML的原理

-DOM方式与SAX方式的区别:DOM方式解析之前要将整个XML文档读入,在内存中产生一个DOM树;而SAX方式解析是逐行扫描文档,边扫描边进行解析,不必等到整个文档装载完才进行操作。
-Java中SAX解析XML的方式:SAX解析方式是基于事件驱动(一种基于回调(callback)机制的程序运行方法)的,利用SAX解析XML涉及解析器和事件处理器两个部分。

a.解析器:对XML文档逐行进行解析,只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的XML文件内容作为方法的参数传递给事件处理器。
b.事件处理器:由程序员编写,决定对从解析器解析到的数据如何做处理。

-解析原理:
XML文档——解析器逐行解析——>解析到元素——-调用相应的时间处理方法——>处理解析到的数据——-继续解析下一行——>……

三、具体的Java代码实现

1.创建解析器,处理器,加载XML文档;2.内容处理的几个主要方法;3.取出特定元素的内容;4.将XML中的信息全部输出

待解析的XML代码:

<?xml version="1.0" encoding="UTF-8" standalone="no"?><联系人列表>
    <联系人>
        <姓名>张三</姓名>
        <EMAIL>[email protected]</EMAIL>
        <年龄>30</年龄>
    </联系人>
    <联系人>
        <姓名>李四</姓名>
        <EMAIL>[email protected]</EMAIL>
        <年龄>31</年龄>
    </联系人>
</联系人列表>

1.创建解析器,处理器,加载XML文档

//创建sax解析器
SAXParser sax = SAXParserFactory.newInstance().newSAXParser();
//获取内容读取器
XMLReader xml = sax.getXMLReader();
//注册一个内容处理器
xml.setContentHandler(new DefaultHandler(){});//重写DefaultHandler接口中的方法来处理解析到的内容
//加载XML文档
xml.parse("src/j2ee/dom/linkman.xml");

2.内容处理用到的几个主要方法(DefaultHandler 接口中)

i.startDocument() 
方法说明:在解析整个文档开始时自动调用,重写此方法可以在解析文档开始时做特定处理。
ii.endDocument() 
方法说明:在解析整个文档结束时自动调用,重写此方法可以在解析整个文档结束时做处理。
iii.startElement(String uri, String localName, String qName, Attributes attributes) 
参数说明:URL,本地名称,当前解析到的元素名称,元素附加的属性
方法说明:在解析到元素节点时自动调用,重写此方法可以在解析到元素节点时做相应处理。
iv.endElement(String uri, String localName, String qName) 
参数说明:URL,本地名称,当前结束解析的元素名称
方法说明:在解析到元素节点结束标签时自动调用,重写此方法可以在解析元素节点结束时做相应处理。
v.characters(char[] ch, int start, int length)
参数说明:XML文档内容的字符数组,当前解析到的元素在字符数组的起始位置,当前解析到的元素所占长度
方法说明:在解析完元素标签方法结束后自动调用,重写此方法可以对在此元素内读取到的相应内容做处理。

解析时方法调用的流程:由startDocument开始,在endDocument结束,中间三个按顺序反复调用

startDocument()---->sartElement()---->characters()---->endElement()---->sartElement()---->characters()---->endElement()---->......--->endDocument()

3.取出特定元素的内容(取出XML中第二个联系人的姓名,运行结果输出“李四”)

//创建sax解析器
SAXParser sax = SAXParserFactory.newInstance().newSAXParser();
//获取内容读取器
XMLReader xml = sax.getXMLReader();
//注册一个内容处理器
xml.setContentHandler(new DefaultHandler(){
    String curname = "";//记录当前的元素名
    int count = 0;//记录当前取到的是第几个联系人
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if(qName.equals("姓名")){
            curname = "姓名";//只关注“姓名”元素
            count++;
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        curname="";//一个元素解析结束后应清空记录的当前元素名
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        if("姓名".equals(curname)&&count==2){  //拿到了第二个联系人的姓名
            System.out.println(new String(ch,start,length));
        }
    }
});
//加载XML文档
xml.parse("src/j2ee/dom/linkman.xml");

4.将XML中的信息全部输出(定义一个linkman类封装信息,此处忽略linkman类的代码之关注主要代码)

List<Linkman> men = new ArrayList<Linkman>();//定义一个容器来存放解析到的联系人对象
//创建sax解析器
SAXParser sax = SAXParserFactory.newInstance().newSAXParser();
//获取内容读取器
XMLReader xml = sax.getXMLReader();
//注册一个内容处理器
xml.setContentHandler(new DefaultHandler(){

    Linkman man;//联系人对象
    String curname = "";//记录当前解析的元素名
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if(qName.equals("联系人")){
            man = new Linkman();//当解析到联系人元素时new一个新的联系人对象
        }
        curname = qName;
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if(qName.equals("联系人")){ //当一个联系人元素解析完成时,将这个联系人对象添加到容器中
            men.add(man);
        }
        curname="";
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        if("姓名".equals(curname)){ 
            man.setName(new String(ch,start,length));//若当前解析的是姓名元素,则将姓名的内容添加给联系人对象
        }
        if("EMAIL".equals(curname)){
            man.setEmail(new String(ch,start,length));//若当前解析的是EMAIL元素,则将Email内容添加给联系人对象
        }
        if("年龄".equals(curname)){
            man.setAge(Integer.parseInt(new String(ch,start,length)));//若当前解析的是年龄元素,则将年龄内容添加给联系人对象
        }
    }
});
//加载XML文档
xml.parse("src/j2ee/dom/book.xml");


for (Linkman tmp: men ) {
    System.out.println(tmp.toString());
}

输出结果如下:(成功将XML中全部信息解析)

张三--zhang3@gmail.com--30
李四--li4@163.com--31
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章