java xml SAX

JAVA xml SAX

概述

SAX,全称Simple API for XML,是一种以事件驱动的XMl API,是XML解析的一种新的替代方法,解析XML常用的还有DOM解析,PULL解析(Android特有),SAX与DOM不同的是它边扫描边解析,自顶向下依次解析,由于边扫描边解析,所以它解析XML具有速度快,占用内存少的优点,对于Android等CPU资源宝贵的移动平台来说是一个巨大的优势。

Java中除了DOM方法可以解析XML文件外,还可以使用Dom、JDOM、DOM4J等方法

步骤

  1. 得到xml文件对应的资源,可以是xml的输入流,文件和uri
  2. 得到SAX解析工厂(SAXParserFactory
  3. 由解析工厂生产一个SAX解析器(SAXParser
  4. 传入输入流和handler给解析器,调用parse()解析

原理

对上图做个简单说明,当当前标签有子标签的时候,该标签先触发characters,然后子标签触发startElement-characters-endElement事件,这个过程可以理解为一个不断递归的过程。

描述SAX解析过程

startDocument-startElement-characters-endElement-endDocument

常用类

SAXParserFactory

public abstract class SAXParserFactory extends Object

  • 概述

定义工厂API,使应用程序能够配置和获取基于SAX的解析器来解析XML文档。

  • 常用方法

    static SAXParserFactorynewInstance() 获得一个新的实例 SAXParserFactory 。

    abstract SAXParsernewSAXParser() 使用当前配置的工厂参数创建SAXParser的新实例。

SAXParser

public abstract class SAXParser extends Object

  • 概述

为了方便转换,此类继续支持相同的名称和界面以及支持新方法。 该类的一个实例可以从SAXParserFactory.newSAXParser()方法获得。 一旦获得此类的实例,可以从各种输入源解析XML。 这些输入源是InputStreams,Files,URL和SAX InputSources。

由内容由底层解析器解析,调用给定HandlerBase(过时)DefaultHandler方法。

  • 常用方法

    void parse(File f, DefaultHandler dh) 解析使用指定的指定XML文件的内容

    DefaultHandler void parse(File f, HandlerBase hb) 解析使用指定的指定XML文件的内容HandlerBase 。 voidparse(InputSource is, DefaultHandler dh) 解析给出的内容InputSource使用指定为XML 、DefaultHandler voidparse(InputSource is, HandlerBase hb) 解析给出的内容InputSource使用指定为XML HandlerBase void parse(InputStream is, DefaultHandler dh) 解析给定的内容InputStream使用指定的实例作为XML

    DefaultHandler voidparse(InputStream is, DefaultHandler dh, String systemId)

    解析给定的内容InputStream使用指定的实例作为XML

    DefaultHandler voidparse(InputStream is, HandlerBase hb)
    解析给定的内容InputStream使用指定的实例作为XML

    HandlerBase voidparse(InputStream is, HandlerBase hb, String systemId)
    解析给定的内容InputStream使用指定的实例作为XML

    HandlerBase voidparse(String uri, DefaultHandler dh)
    使用指定的DefaultHandler解析使用给定统一资源标识符(URI)作为XML描述的内容

    void parse(String uri, HandlerBase hb)
    使用指定的HandlerBase解析使用给定统一资源标识符(URI)作为XML描述的内容 。

DefaultHandler

public class DefaultHandler extends Object implements EntityResolver, DTDHandler, ContentHandler, ErrorHandler

  • 概述

该类可用作SAX2应用程序的便利基类:它为四个核心SAX2处理程序类中的所有回调提供了默认实现:

应用程序编写者可以在需要仅实现部分接口时扩展此类; 解析器作者可以实例化这个类,以便在应用程序没有提供自己的时候提供默认处理程序。

该类替代了不赞成使用的SAX1 HandlerBase类。

  • 常用方法

public void characters(char[] ch, int start, int length)throws SAXException

接收元素内的字符数据通知。

默认情况下,什么也不做。 应用程序编写者可以覆盖此方法以对每个字符数据块采取特定操作(例如将数据添加到节点或缓冲区,或将其打印到文件中)。

ch - 字符。 start - 字符数组中的起始位置。 length - 从字符数组中使用的字符数。

public void endDocument() throws SAXException

接收文件结尾的通知。
默认情况下,什么也不做。 应用程序编写者可以在子类中覆盖此方法,以在文档的末尾执行特定操作(例如,最终确定树或关闭输出文件)。

public void endElement(String uri, String localName, String qName) throws SAXException

接收元素结尾的通知。
默认情况下,什么也不做。 应用程序编写者可以在子类中覆盖此方法,以在每个元素的末尾执行特定操作(例如,完成树节点或将输出写入文件)。

uri - 名称空间URI,或空字符串,如果该元素没有命名空间URI或未命名空间处理。 localName - 本地名称(无前缀),或空字符串,如果未执行命名空间处理。 qName - 限定名称(带前缀),如果限定名称不可用,则为空字符串。

public void startElement(String uri, String localName, String qName,Attributes attributes)throws SAXException

接收元素开始的通知。
默认情况下,什么也不做。 应用程序编写者可以在子类中覆盖此方法,以在每个元素的开始处采取特定的操作(例如分配新的树节点或将输出写入文件)。

uri - 命名空间URI,如果该元素没有命名空间URI或未执行命名空间处理,则为空字符串。 localName - 本地名称(无前缀),或空字符串,如果未执行命名空间处理。 qName - 限定名称(带前缀),如果限定名称不可用,则为空字符串。 attributes - 附加到元素的属性。 如果没有属性,它将是一个空的Attributes对象。

public void startDocument() throws SAXException

接收文件开头的通知。
默认情况下,什么也不做。 应用程序编写者可以在子类中覆盖此方法,以在文档的开头执行特定操作(例如分配树的根节点或创建输出文件)。

DefaultHandler2

public class DefaultHandler2 extends DefaultHandler implements LexicalHandler, DeclHandler, EntityResolver2

  • 概述

此类扩展SAX2基本处理程序类,以支持SAX2 LexicalHandlerDeclHandlerEntityResolver2扩展。 除了覆盖原来的SAX1 resolveEntity()方法,添加的处理程序方法只是返回。 子类可以逐个方法地覆盖所有内容。

  • 常用方法

void attributeDecl(String eName, String aName, String type, String mode, String value)
报告属性类型声明。

void comment(char[] ch, int start, int length)
在文档的任何位置报告XML注释。

void elementDecl(String name, String model)
报告元素类型声明。

void endCDATA()
报告CDATA部分的结尾。

void endDTD()
报告DTD声明的结尾。

void endEntity(String name)
报告实体的结束。

void externalEntityDecl(String name, String publicId, String systemId)
报告被解析的外部实体声明。
InputSource getExternalSubset(String name, String baseURI)
告诉解析器,如果在文档文本中没有声明外部子集,则不应使用任何外部子集。

void internalEntityDecl(String name, String value)
报告内部实体声明。
InputSource resolveEntity(String publicId, String systemId)
使用null实体名称和基本URI调用 EntityResolver2.resolveEntity()

InputSourcere solveEntity(String name, String publicId, String baseURI, String systemId)
告诉解析器根据baseURI解析systemId,并从该结果的绝对URI中读取实体文本。

void startCDATA()
报告CDATA部分的开始。

void startDTD(String name, String publicId, String systemId)
报告DTD声明的开始,如果有的话。

void startEntity(String name)
报告一些内部和外部XML实体的开始。

实例

public class Person extends DefaultHandler {

    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Person() {}

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

}



class entityHandler extends DefaultHandler {

    private List<Person> list;
    private Person p;
    private String result;

    // 开始读取文件的方法,可以在这个方法内加入一些初始化的代码
    @Override
    public void startDocument() throws SAXException {
        System.out.println("开始解析");
        this.list = new ArrayList<>();
    }

    //endDocument():文件读取结束时执行。
    @Override
    public void endDocument() throws SAXException {
        System.out.println("结束解析");
    }

    //startElement():读取某一个标签的方法,参数中的qName代表这个标签的内容。
// 例如:被<>包裹的标签qName就是两个尖括号中的文字。每次读到一个<>都会调用这个方法,
// 例如:<name>至尊宝</name>,qName就是“name”,startElement()执行完后会执行一次characters()
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
//                uri - 命名空间URI,如果该元素没有命名空间URI或未执行命名空间处理,则为空字符串。
//                localName - 本地名称(无前缀),或空字符串,如果未执行命名空间处理。
//                qName - 限定名称(带前缀),如果限定名称不可用,则为空字符串。
//                attributes - 附加到元素的属性。 如果没有属性,它将是一个空的Attributes对象。
        if (qName != null) {
            String str = qName.toLowerCase();
            this.result = str;
            if (str.equals("person")) {
                this.p = new Person();
            }
        }


    }

    //            endElement():读取到</>结构时执行,qName返回的是其中的内容,
//            例如:<name>至尊宝</name>,qName就是“name”, endElement()执行完后也会执行一次characters()
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
//                uri - 名称空间URI,或空字符串,如果该元素没有命名空间URI或未命名空间处理。
//                localName - 本地名称(无前缀),或空字符串,如果未执行命名空间处理。
//                qName - 限定名称(带前缀),如果限定名称不可用,则为空字符串。
        if (qName != null) {
            if (qName.toLowerCase().equals("person")) {
                this.list.add(this.p);
                this.p = null;
            }
        }
        this.result = null;

    }


    //characters():标签中属性的方法,ch[]就是其中的内容,每次执行完startElement和endElement都会执行此方法。
// 例如:<name>至尊宝</name>,ch[]就是“至尊宝”三个字,由于多层的结构,所以很多时候ch[]都为空,应该注意一下
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        System.out.println(this.result);
//                ch - 字符。
//                start - 字符数组中的起始位置。
//                length - 从字符数组中使用的字符数。
        String string = new String(ch, start, length);
        if (string != null && this.result != null) {
            if (this.result.equals("name")) {
                this.p.setName(string);
            } else if (this.result.equals("age")) {
                this.p.setAge(new Integer(string));
            }
        }


    }

    public List<Person> getList() {
        return list;
    }

    public void setList(List<Person> list) {
        this.list = list;
    }
}


public class SAX {

    @Test
    public void test() throws ParserConfigurationException, SAXException, IOException {

        // SAX解析
        // 1、获取解析工厂
        SAXParserFactory factory = SAXParserFactory.newInstance();
        // 2、从解析工厂获取解析器
        SAXParser parser = factory.newSAXParser();

        DefaultHandler handler = new entityHandler();

        parser.parse(new File("dom.xml"), handler);

        for (Person person : ((entityHandler) handler).getList()) {
            System.out.println(person.getName() +"=>"+ person.getAge());
        }

    }


}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值