解析XML文件之使用SAM解析器
XML是一种常见的传输数据方式,所以在开发中,我们会遇到对XML文件进行解析的时候,本篇主要介绍使用SAM解析器,对XML文件进行解析。
SAX解析器的长处是显而易见的。那就是SAX并不须要将全部的文档都载入内存之后才进行解析。SAX是事件驱动机制的。也就是碰到元素节点、文本节点、文档节点的时候。都会触发一定的事件。我们仅仅须要在对应的回调事件里面进行对应的处理就能够了。由于这个特点。所以SAX解析占用的内存比較少。其它的解析方式,比方下一节要介绍的DOM解析器。则占用内存比較多。在解析比較小的XML文件的时候,差别不是非常大。大家哪种顺手就能够用哪种。可是当须要解析的文档达到几百K以上的时候,还是推荐使用SAX解析器或者是PULL解析器。这几种XML的解析方式。我都会在以后的文章中进行介绍,今天重点看SAX解析器。
以下是我们要进行解析的文件格式
<?xml version="1.0" encoding="UTF-8"?> <persons> <person id="23"> <name>liming</name> <age>30</age> </person> <person id="20"> <name>lixiangmei</name> <age>25</age> </person> </persons>
以下是我们的实体类
public class Person { private Integer id; private String name; private Short age; public Person(){} public Person(Integer id, String name, Short age) { this.id = id; this.name = name; this.age = age; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Short getAge() { return age; } public void setAge(Short age) { this.age = age; } @Override public String toString() { return "Person [age=" + age + ", id=" + id + ", name=" + name + "]"; } }
我们定义一个SAM解析器。对内容进行解析
/** * 使用SAX对XML文件进行解析 * * @author zhaokaiqiang * */ public class SaxResolve { public List<Person> getPersons(InputStream inputStream) throws Exception { //获取SAXParser对象 SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); //实例化我们的解析器 PersonHandler handler = new PersonHandler(); //開始对输入流解析 parser.parse(inputStream, handler); //关闭输入流 inputStream.close(); //返回结果 return handler.getPersons(); } private class PersonHandler extends DefaultHandler { private List<Person> persons; private Person person = null; private String tag = null; public List<Person> getPersons() { return persons; } // 当读取到xml文件的開始部分时。对persons进行初始化 @Override public void startDocument() throws SAXException { persons = new ArrayList<Person>(); } // 这种方法对元素节点进行解析,如我们数据中的<person>、<age>、<name>都属于元素节点 // 当读取到person节点时,对Person对象进行初始化,同一时候获取到属性节点的值。并赋值给id, // 记录如今的节点的名称,即localName,用于Person节点内部节点的解析 @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (localName.equals("person")) { person = new Person(); person.setId(new Integer(attributes.getValue(0))); } tag = localName; } // 这个回调方法用于对文本节点进行解析,如<age>30</age>里面的30就是属于文本节点。 // 我们依据元素节点tag的取值,取出里面的文本节点。然后对person进行赋值 @Override public void characters(char[] ch, int start, int length) throws SAXException { if (tag != null) { String data = new String(ch, start, length); if ("name".equals(tag)) { person.setName(data); } else if ("age".equals(tag)) { person.setAge(new Short(data)); } } } /* * 当到达一个元素节点的结束时 比方 * <person id="20"> * <name>lixiangmei</name> * <age>25</age> * </person> * 当到达这里的</person>节点,就会出发以下的事件,我们在这个回调方法里面将解析出的person对象 * 加入到persons里面,而且将person和tag进行初始化,进行下一个person节点的解析 */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { if (localName.equals("person")) { persons.add(person); person = null; } tag = null; } } }
由于凝视比較具体,所以只是多解析,以下我们使用单元測试,对解析进行測试
//測试SAX解析 public void testSax() throws Exception { //从xml文件里获取输入流 InputStream inputStream = getClass().getClassLoader() .getResourceAsStream("persons.xml"); //获取解析出的对象 List<Person> persons = new SaxResolve().getPersons(inputStream); //打印 for (Person p : persons) { Log.d(TAG, p.toString()); } }
以下是解析结果