SAX(Simple API for XML)解析器是一种基于事件的解析器,它的核心是事件处理模式,主要是围绕着事件源以及事件处理器来工作的。当事件源产生事件后,调用事件处理器相应的处理方法,一个事件就可以得到处理。在事件源调用事件处理器中特定方法的时候,还要传递给事件处理器相应事件的状态信息,这样事件处理器才能够根据提供的事件信息来决定自己的行为。
SAX解析器的优点是解析速度快,占用内存少。非常适合在Android移动设备中使用。
SAX相关类及API
DefaultHandler:是一个事件处理器,可以接收解析器报告的所有事件,处理所发现的数据。它实现了EntityResolver接口、DTDHandler接口、ErrorHandler接口和ContentHandler接口。这几个接口代表不同类型的事件处理器。
利用SAX解析XML,实际上只需要继承DefaultHandler类,然后重写几个关键性方法即可。一般我们需要重写的方法是startDocument、startElement、characters、endElement和endDocument方法。
API解释:
1 import org.xml.sax.Attributes; 2 import org.xml.sax.SAXException; 3 import org.xml.sax.helpers.DefaultHandler; 4 5 public class MyParser extends DefaultHandler{ 6 7 /** 8 * 当文档开始解析时此函数被调用 9 * 10 * 通常我们需要在这里面做一些初始化的工作,比如分配某些资源11 */12 @Override13 public void startDocument() throws SAXException {14 super.startDocument();15 }16 17 /**18 * 当扫描到文档元素节点起始标志时被调用19 * 20 * 通常我们需要做一下标记,或者分配节点资源。21 */22 @Override23 public void startElement(String uri, String localName, String qName,24 Attributes attributes) throws SAXException {25 super.startElement(uri, localName, qName, attributes);26 }27 28 /**29 * 扫描到元素节点中的字符串内容时调用此函数30 * @param ch 代表元素内容的字符数组(实测时候并不完全表示元素内容,不过这不影响)31 * @param start 能够使用的起始位置32 * @param length 能够使用的数组长度33 */34 @Override35 public void characters(char[] ch, int start, int length)36 throws SAXException {37 super.characters(ch, start, length);38 }39 40 41 /**42 * 扫描到元素节点结束标志时调用43 * 44 * 应该是最重要的一个方法。需要判断节点名作相应的数据解析。45 * @param localName 节点名字46 * @param qName 含限定符的节点名字47 */48 @Override49 public void endElement(String uri, String localName, String qName)50 throws SAXException {51 super.endElement(uri, localName, qName);52 }53 54 /**55 * 扫描文档结束后调用56 * 57 * 如果有些资源需要释放的话,就在这里做好了。58 */59 @Override60 public void endDocument() throws SAXException {61 super.endDocument();62 }63 64 }
实例
需要解析的persons.xml文件内容如下:
1 23 4 7张三 524 68 11李四 925 1012 15王五 1326 14
定义Person实体类:
/** * Created by Shane on 2015/4/24. */public class Person { private int id; private int group; private String name; private int age; public int getId() { return id; } public void setId(int id) { this.id = id; } public int getGroup() { return group; } public void setGroup(int group) { this.group = group; } 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; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("name: " + name); sb.append(", age: " + age); sb.append(", id: " + id); sb.append(", group: " + group); return sb.toString(); }}
定义用于解析XML文件的解析器PersonSAXHandler 类如下:
/** * Created by Shane on 2015/4/24. */public class PersonSAXHandler extends DefaultHandler{ private static final String TAG_PERSON = "person"; private static final String TAG_NAME = "name"; private static final String TAG_AGE = "age"; private Listpersons; private Person person; private StringBuffer stringBuffer; public List getPersons() { return persons; } @Override public void startDocument() throws SAXException { super.startDocument(); persons = new ArrayList<>(); stringBuffer = new StringBuffer(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); if (localName.equals(TAG_PERSON)) { person = new Person(); person.setId(Integer.parseInt(attributes.getValue(0))); person.setGroup(Integer.parseInt(attributes.getValue(1))); } stringBuffer.setLength(0); // start a new string buffer. } @Override public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); stringBuffer.append(ch, start, length); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); if (localName.equals(TAG_PERSON)) { persons.add(person); } else if (localName.equals(TAG_NAME)) { person.setName(stringBuffer.toString().trim()); } else if (localName.equals(TAG_AGE)) { person.setAge(Integer.parseInt(stringBuffer.toString().trim())); } } @Override public void endDocument() throws SAXException { super.endDocument(); }}
包装上述PersonSAXHandler类,定义PersonSAXParser类进行解析:
/** * Created by Shane on 2015/4/24. */public class PersonSAXParser implements PersonParser{ @Override public Listparse(InputStream inputStream) { List persons = new ArrayList<>(); try { SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser(); PersonSAXHandler personSAXHandler = new PersonSAXHandler(); saxParser.parse(inputStream, personSAXHandler); persons = personSAXHandler.getPersons(); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) {} } } return persons; }}
PersonParser接口定义如下:
/** * Created by Shane on 2015/4/24. */public interface PersonParser { public Listparse(InputStream inputStream); }