加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

SAX解析XML文件

发布时间:2020-12-16 00:17:36 所属栏目:百科 来源:网络整理
导读:DOM:文档驱动。DOM在解析文件之前把整个文档装入内存,处理大型文件时其性能很差,是由于DOM的树结构所造成的,此结构占用的内存较多。 SAX(simple API for XML)采用事件驱动的方式解析文档。简单点说,如同在电影院看电影一样,从头到尾看一遍就完了,不

DOM:文档驱动。DOM在解析文件之前把整个文档装入内存,处理大型文件时其性能很差,是由于DOM的树结构所造成的,此结构占用的内存较多。

SAX(simple API for XML)采用事件驱动的方式解析文档。简单点说,如同在电影院看电影一样,从头到尾看一遍就完了,不能回退(DOM可来来回回读取)在看电影的过程中,每遇到一个情节,一段泪水,一次擦肩,你都会调动大脑和神经去接收或处理这些信息。同样,在SAX的解析过程中,读取到文档开头、结尾,元素的开头和结尾都会触发一些回调方法,你可以在这些回调方法中进行相应事件处理。这四个方法是:
startDocument() 、 endDocument()、 startElement()、 endElement()
此外,光读取到节点处是不够的,我们还需要characters()方法来仔细处理元素内包含的内容。将这些回调方法集合起来,便形成了一个类,这个类也就是我们需要的触发器。
一般从main()方法中读取文档,却在触发器中处理文档,这就是所谓的事件驱动解析方法。

如上图,在触发器中,首先开始读取文档,然后开始逐个解析元素,每个元素中的内容会回调characters()方法,接着结束元素读取,所有元素读取完后,结束文档解析。

SAX解析原理:

通过自己创建的Handler处理类去逐个分析(从最外层到最里层依次去遍历每一个节点)遇到的每一个节点(通过startElement()方法解析开始标记,通过endElement方法解析结束标记)。

SAX方式解析XML文件的步骤:

  1. 通过SAXParserFactory的静态方法newInstance()方法获取SAXParserFactory的实例factory;
  2. 通过SAXParserFactory实例的newSAXParser()方法返回一个SAXParser实例parser;
  3. 创建一个类继承自DefaultHandler,重写其中的一些方法进行业务处理并创建这个类的实例handler;
  4. 通过SAXParser对象的parse(String uri,DefaultHandler dh)方法解析xml文件。

关于XML文件的解析开始和解析结束:

  • 解析开始:当handler指向XML声明;
<?xml version = "1.0" encoding = "utf-8"?>
  • 解析结束:当handler指向最后一个结束标记。
</bookstore>

实现如下:

import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

public class SAXTest {

    public static void main(String[] args) {
    // 1.获取一个SAXParserFactory的实例
    SAXParserFactory factory = SAXParserFactory.newInstance();
    try {
        // 2.通过factory获取SAXParser实例
        SAXParser parser = factory.newSAXParser();
        //3.创建一个SAXParserHandler对象
        SAXParserHandler handler = new SAXParserHandler();
        //4.通过SAXParser对象的parse(String uri,DefaultHandler dh)方法解析xml文件
        parser.parse("books.xml",handler);
    } catch (ParserConfigurationException e) {
        e.printStackTrace();
    } catch (SAXException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    }

}
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/** * 创建一个类继承自DefaultHandler,重写其中的一些方法用来进行业务处理 * */
public class SAXParserHandler extends DefaultHandler {
    int bookIndex = 0;// 定义一个全局变量用于保存当前遍历的书的索引(当前正在遍历第几本书)

    /** * 用来标志解析开始 */
    @Override
    public void startDocument() throws SAXException {
    super.startDocument();
    System.out.println("=============== SAX解析开始 ===============n");
    }

    /** * 用来标志解析结束 */
    @Override
    public void endDocument() throws SAXException {
    super.endDocument();
    System.out.println("=============== SAX解析结束 ===============");
    }

    /** * 解析XML文件的开始标签,uri-名称空间,localName-名称空间的标签,如果没有名称空间,则为空 * qName-标签名,attributes-属性集合 */
    @Override
    public void startElement(String uri,String localName,String qName,Attributes attributes) throws SAXException {
    super.startElement(uri,localName,qName,attributes);
    System.out.println(">>>>>>>>>>>开始解析元素:" + qName);
    // 仅仅book节点有属性
    if ("book".equals(qName)) {
        bookIndex++;
        System.out.println("***********开始遍历第" + (bookIndex)
            + "本书***********");
        // 已知book元素有属性名称id,根据属性名获取属性值
        // String attrValue = attributes.getValue("id");
        // System.out.println("book的属性值是:"+attrValue);
        // 不知道book元素的属性名以及属性的个数
        int numberOfAttributes = attributes.getLength();// 获取属性个数
        for (int i = 0; i < numberOfAttributes; i++) {
        System.out.print("book元素的第" + (i + 1) + "个属性名:"
            + attributes.getQName(i));
        System.out.println(",属性值:" + attributes.getValue(i));
        }
    } else if (!"bookstore".equals(qName)) {
        System.out.print("节点名:" + qName);
    }
    }

    /** * 字符数组ch-元素中的内容,start-开始位置,length-长度 */
    @Override
    public void characters(char[] ch,int start,int length)
        throws SAXException {
    super.characters(ch,start,length);
    String value = new String(ch,length);
    if (!"".equals(value.trim())) {// 过滤空白文本(和DOM类似)
        System.out.println("-节点值:" + value);
    }
    }

    /** * 解析XML文件的结束标签 */
    @Override
    public void endElement(String uri,String qName)
        throws SAXException {
    super.endElement(uri,qName);
    System.out.println("<<<<<<<<<<<结束解析" + qName);
    // 判断是否一本书遍历结束(handler指向</book>)
    if ("book".equals(qName)) {
        System.out.println("***********结束遍历第" + (bookIndex)
            + "本书***********n");
    }
    }
}

运行结果:

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读