Java 操作 xml 文件之 SAX 解析

  1. dom4j 解析:文档对象模型解析,是W3C指定的一套规范标准。需要把整个文档读取到内存中,占用内存大,解析慢,但是访问效率高,增删改查快。适合解析小型文档。
  2. SAX 解析:基于事件驱动解析文档,边读边解析,不必解析整个文档,解析速度快,但是访问效率低,只能从开始顺序解析。

      • 2、SAX 解析
          • 输出到控制台
          • 封装成对象

2、SAX 解析

SAX 解析是基于事件驱动的,先介绍以下五个方法:

(1) void startDocument(); 解析文档开始时执行
(2) void endDocument(); 解析文档结束时执行
(3) void startElement(String uri, String localName, String qName,Attributes attributes); 遇到元素开始节点时执行
(4) void characters(char[] ch, int start, int length); 两尖括号之间时执行
(5) void endElement(String uri, String localName, String qName); 遇到元素结束节点时执行

Java 操作 xml 文件之 SAX 解析_第1张图片

输出到控制台
import java.io.IOException;

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

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

public class SAXParserHandler extends DefaultHandler {
    int comIndex = 0;

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

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

    // 解析xml元素,每到开始标签都会调用下面这个方法
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        // 调用defaultHandler类的startElement方法
        super.startElement(uri, localName, qName, attributes);
        if (!qName.equals("city")&&!qName.equals("company")&&!qName.equals("person")) {
            System.out.print("节点名是:" + qName);
        }
        if (qName.equals("company")) {
            comIndex++; 
            System.out.println("开始遍历第" + comIndex + "个公司资料");
            System.out.println("节点名是:" + qName);
        }

        // 开始解析company元素的属性(已知company元素下的属性名称,根据名称获取属性值)
        if (qName.equals("company")) {
            String value = attributes.getValue("unitId");
            System.out.println("company的unitId属性值是" + value);
            String value2 = attributes.getValue("unitCode");
            System.out.println("company的unitCode属性值是" + value2);
            String value3 = attributes.getValue("unitName");
            System.out.println("company的unitName属性值是" + value3);
        }
/*
        // 不知道元素节点中属性的名称及个数,如何获取属性名和属性值
          int num = attributes.getLength();// 返回book元素下属性的个数 
          for (int i = 0; i < num; i++) { 
           System.out.print("company元素的第" + (i + 1) + "个属性名是:" + attributes.getQName(i)); 
           System.out.println("---属性值是:" + attributes.getValue(i));
         }
*/       
    }

    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        super.endElement(uri, localName, qName);
        // 判断是否对某一元素节点已经遍历结束
        if (qName.equals("company")) {
            System.out.println("结束遍历第" + comIndex + "个公司的资料");
            System.out.println();
        }
    }

    @Override
    // char[] ch代表相邻两个尖括号<>之间的内容
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        super.characters(ch, start, length);
        String value = new String(ch, start, length);
        if (!value.trim().equals("")) {
            System.out.println("=="+value);
        }
    }

    public static void main(String[] args) {
        String pathname = "E://temptest//xmlTest.xml";
        // 获取SAXParserFactory实例
        SAXParserFactory factory=SAXParserFactory .newInstance();
        //获取SAXParse的实例
        try {
            SAXParser parser=factory.newSAXParser();
            //创建SAXParserHandler对象
            SAXParserHandler handler=new SAXParserHandler();

            parser.parse(pathname, handler);
            } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
}
封装成对象
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

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

public class SAXReadXml extends DefaultHandler {
    private List> conList= new ArrayList>();
    private HashMap map;// 用来封装 company 对象ֵ
    private String elementName;// 节点名称

    public void reader(String pathfile) {
        InputStream inStream = null;
        try {
            inStream = new FileInputStream(pathfile);
            SAXParserFactory saxfac = SAXParserFactory.newInstance();
            SAXParser saxParser = saxfac.newSAXParser();
            saxParser.parse(inStream, this);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                inStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    StringBuffer text = new StringBuffer("");

    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        elementName = qName;
        if (qName.equals("company")||qName.equals("person")) {
            map = new HashMap();
        }
    }

    @Override
    public void characters(char[] ch, int start, int length)throws SAXException {
        if (map != null && elementName != null) {
            String content = new String(ch, start, length);
            if (content.trim().length() > 0) {
                text.append(new String(ch, start, length));
                map.put(elementName, text.toString());
            }
            //如果是用某个对象的set方法赋值,则先判断节点名称
        //  if(elementName.equals("userName")) {
        //      user.setName(text.toString()); //假设给user对象的name赋值
        //  }
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName)throws SAXException {
    //  if (qName.equals("company")||qName.equals("person")){ //把 company 和 person 的对象添加到 list
    //      conList.add(map);
    //  }
        if (qName.equals("company")) {//只把 company 的对象添加到 list 
            conList.add(map);
        }
        elementName = null;
        text = new StringBuffer("");
    }

    //用来返回封装好的对象列表
    public  List> getCompanyList(){
        return conList;
    }

    public static void main(String[] args) {
        SAXReadXml xml = new SAXReadXml();
        xml.reader("E:\\temptest\\xmlTest.xml");
        List> list = xml.getCompanyList();
        for(Map com:list){
            System.out.println(com);
        }
    }
}

不管我们要哪类还是哪个元素节点的内容,只要在 startElement 方法、characters 方法、endElement 方法中加入相应的判断、逻辑,就能解析到我们想要的内容,所以,尽管 SAX 解析比较麻烦,但是更灵活。

你可能感兴趣的:(Java,xml)