1. SAX(Simple API for XML)
SAX处理的优点非常类似于流媒体的优点。分析能够立即开始,而不是等待所有的数据被处理。而且,由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中。这对于大型文档来说是个巨大的优点。事实上,应用程序甚至不必解析整个文档;它可以在某个条件得到满足时停止解析。一般来说,SAX还比它的替代者DOM快许多。
选择DOM还是选择SAX? 对于需要自己编写代码来处理XML文档的开发人员来说, 选择DOM还是SAX解析模型是一个非常重要的设计决策。 DOM采用建立树形结构的方式访问XML文档,而SAX采用的是事件模型。
DOM解析器把XML文档转化为一个包含其内容的树,并可以对树进行遍历。用DOM解析模型的优点是编程容易,开发人员只需要调用建树的指令,然后利用navigation APIs访问所需的树节点来完成任务。可以很容易的添加和修改树中的元素。然而由于使用DOM解析器的时候需要处理整个XML文档,所以对性能和内存的要求比较高,尤其是遇到很大的XML文件的时候。由于它的遍历能力,DOM解析器常用于XML文档需要频繁的改变的服务中。
SAX解析器采用了基于事件的模型,它在解析XML文档的时候可以触发一系列的事件,当发现给定的tag的时候,它可以激活一个回调方法,告诉该方法制定的标签已经找到。SAX对内存的要求通常会比较低,因为它让开发人员自己来决定所要处理的tag.特别是当开发人员只需要处理文档中所包含的部分数据时,SAX这种扩展能力得到了更好的体现。但用SAX解析器的时候编码工作会比较困难,而且很难同时访问同一个文档中的多处不同数据。
【优势】 ①不需要等待所有数据都被处理,分析就能立即开始。 ②只在读取数据时检查数据,不需要保存在内存中。 ③可以在某个条件得到满足时停止解析,不必解析整个文档。 ④效率和性能较高,能解析大于系统内存的文档。
【缺点】 ①需要应用程序自己负责TAG的处理逻辑(例如维护父/子关系等),文档越复杂程序就越复杂。 ②单向导航,无法定位文档层次,很难同时访问同一文档的不同部分数据,不支持XPath。
2. 解析步骤很简单,可分为以下四个步骤
得到xml文件对应的资源,可以是xml的输入流,文件和uri得到SAX解析工厂(SAXParserFactory)由解析工厂生产一个SAX解析器(SAXParser)传入输入流和handler给解析器,调用parse()解析 step1: XML文件 <?xml version="1.0" encoding="UTF-8"?> <users nihao="hello" xmlns="http://test.org/books"> <user id="0"> <name>xiazhang</name> <age>23</age> <sex>男</sex> </user> <user id="1"> <name>jinnan</name> <age>25</age> <sex>女</sex> </user> </users> step2: 建一个JavaBean /** * sax解析xml bean * * @author xiazhang * @date 2017-6-7 */ public class SaxUser { private int id; private String name; private int age; private String sex; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } } step3: 新建一个类 XmlParseHandler.java ,该类需要继承 DefaultHandler 或者实现 ContentHandler 接口, 这里我们通过继承 DefaultHandler (实现了 ContentHandler 接口)的方式,该类是SAX解析的核心所在 需要重写5个方法 /** * * @author xiazhang * @date 2017-6-7 */ public class XmlParseHandler extends DefaultHandler{ private List<SaxUser> saxUsers; //记录当前解析得到的解析名称 private String currentTag; //记录房钱user private SaxUser saxUser; /** * 文档解析开始时调用 */ @Override public void startDocument() throws SAXException{ super.startDocument(); saxUsers = new ArrayList<SaxUser>(); } /** * 节点解析开始时调用 * @param uri 命名空间 * @param localName 标签名称 * @param qName 带命名空间的标签名称 * @param attributes 标签的属性集 */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes ) throws SAXException{ super.startElement(uri, localName, qName, attributes); if("user".equals(qName)){ for(int i = 0; i < attributes.getLength(); i++){ saxUser = new SaxUser(); if("id".equals(attributes.getLocalName(i))){ saxUser.setId(Integer.valueOf(attributes.getValue(i))); } } } //记录当前标签名 currentTag = qName; } /** * * @param ch 当前读取到的TextNode(文本节点)的字节数组 * @param start 字节开始的位置,为0则读取全部 * @param length 当前TextNode的长度 */ @Override public void characters(char[] ch, int start, int length) throws SAXException{ super.characters(ch, start, length); //将当前TextCode转换为String String value = new String(ch,start,length); if("name".equals(currentTag)){//name节点 saxUser.setName(value); }else if("age".equals(currentTag)){ saxUser.setAge(Integer.valueOf(value)); }else if("sex".equals(currentTag)){ saxUser.setSex(value); } } /** * 节点解析结束后调用 * @param uri 命名空间 * @param localName 标签名称 * @param qName 带命名空间的标签名称 */ @Override public void endElement(String uri, String localName, String qName) throws SAXException{ super.endElement(uri, localName, qName); if("user".equals(qName)){ saxUsers.add(saxUser); saxUser = null; } currentTag = null; } /** * 文档解析结束时调用 */ @Override public void endDocument() throws SAXException{ super.endDocument(); } public List<SaxUser> getSaxUsers() { return saxUsers; } } step4: 解析 /** * SAX解析XML * * @author xiazhang * @date 2017-6-7 */ public class SaxParseXmlTest { public List<SaxUser> getSaxUsers() throws ParserConfigurationException, SAXException, IOException{ XmlParseHandler handler = new XmlParseHandler(); //1.得到SAX解析工厂 SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); //2.让工厂圣诞一个sax解析器 SAXParser saxParser = saxParserFactory.newSAXParser(); //3.传入输入流和handler解析 saxParser.parse("testXml.xml", handler); //is.close(); return handler.getSaxUsers(); } public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException { SaxParseXmlTest saxParseXmlTest = new SaxParseXmlTest(); List<SaxUser> users = saxParseXmlTest.getSaxUsers(); for (SaxUser saxUser : users) { System.out.println(saxUser.getId()+","+saxUser.getName()+","+saxUser.getAge()+","+saxUser.getSex()); } } }