Android系统开发之XML文件的解析
我们知道Http在网络传输中的数据组织方式有三种分别为:XML方式、HTML方式、JSON方式。其中XML为可扩展标记语言,如下:
<?xml version="1.0" encoding="UTF-8"?> <persons> <person id="23"> <name>Jack</name> <age>23</age> </person> <person id="20"> <name>Tom</name> <age>25</age> </person> </persons>
Android中解析XML数据有三种方式:分别为 DOM、SAX、和XMLPULL。下面我们分别介绍这三种方式:
1)SAX(org.xml.sax) 方式
Simple API for XML,以事件的形式通知程序,对XML进行解析。SAX是一种以事件驱动的XML api,由他定义的事件流可以指定从解析器传到专门的处理程序的代码的XML结构,特点是:解析速度快,占用内存少。
代码流程:
1) 定义一个类继承于DefaultHandler,重写其startDocument、startElement、endDocument、endElement、characters三个方法。
public class MySaxHandler extends DefaultHandler { private HashMap<String, String> map = null; // 存储单个解析的完整对象 private List<HashMap<String, String>> list = null; // 存储所有的解析对象 private String currentTag = null; // 正在解析的元素的标签 private String currentValues = null; // 解析当前元素的值 private String nodeName = null; // 解析当前的节点名称 public MySaxHandler(String nodeName) { // TODO Auto-generated constructor stub this.nodeName = nodeName; } /** * @return the list */ public List<HashMap<String, String>> getList() { return list; } @Override public void startDocument() throws SAXException { // 当读到第一个开始标签的时候触发 list = new ArrayList<HashMap<String,String>>(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { // 当遇到文档的开头的时候触发 if(qName.equals(nodeName)) { map = new HashMap<String, String>(); } if(attributes != null && map != null) { for(int i = 0; i < attributes.getLength(); i++) { map.put(attributes.getQName(i),attributes.getValue(i)); } } currentTag = qName; } @Override public void endDocument() throws SAXException { // TODO Auto-generated method stub super.endDocument(); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { // 遇到结束标记的时候调用 if(qName.equals(nodeName)) { list.add(map); map = null; } } @Override public void characters(char[] ch, int start, int length) throws SAXException { // 处理XML文件所读取到的内容 if(currentTag != null && map != null) { currentValues = new String(ch, start, length); if(currentValues != null && !currentValues.trim().equals("") && !currentValues.trim().equals("\n")) { map.put(currentTag, currentValues); } } currentTag = null; // 当前节点对应的值和标签设置为空 currentValues = null; } }
2) 定义一个处理流的类SaxService,调用SAXParserFactory创建一个SAXParser从输入流解析XML文件。
public class SaxService { public static List<HashMap<String, String>> readXml( InputStream inputStream, String nodeName) { try { // 创建一个解析XML的工厂对象 SAXParserFactory spFactory = SAXParserFactory.newInstance(); SAXParser parser = spFactory.newSAXParser(); MySaxHandler handler = new MySaxHandler(nodeName); parser.parse(inputStream, handler); inputStream.close(); return handler.getList(); } catch (Exception e) { // TODO: handle exception } return null; } public SaxService() { } }
3) 定义一个测试类Test,读取文件FileInputStream调用SaxService.readXml()处理。
public class Test { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub try { File file = new File("C://test.xml"); if(file.exists()) { FileInputStream inputStream = new FileInputStream(file); List<HashMap<String, String>> list = SaxService.readXml(inputStream, "person"); for(HashMap<String, String> map : list) { System.out.println(map.toString()); } } else { System.out.println("file is not exitst"); } } catch (Exception e) { // TODO: handle exception } } }
2)DOM方式
DOM是一种用于XML文档对象模型,可用于直接访问XML文档的各个部位,在DOM中文档被模拟为树桩
其中XML语法的每一个组成部分都表示一个节点,DOM允许用户遍历文档树,从父节点到子节点
和兄弟节点,并利用某节点类型特有的属性。
节点类型:
整个文档是一个节点文档,每个xml标签是一个元素节点,包含在XML元素中的文本是文本节点每个XML属性是一个属性节点。
public class DomXml { public DomXml() { // TODO Auto-generated constructor stub } public List<Person> getPersons(InputStream inputStream) throws Exception { List<Person> list = new ArrayList<Person>(); // 创建一个document解析的工厂 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(inputStream); Element element = document.getDocumentElement(); NodeList personNodeList = element.getElementsByTagName("person"); for(int i = 0; i < personNodeList.getLength(); i++) { Element personElement = (Element)personNodeList.item(i); Person person = new Person(); person.setId(Integer.parseInt(personElement.getAttribute("id"))); NodeList childNodes = personElement.getChildNodes(); for(int j = 0; j < childNodes.getLength(); j++) { if(childNodes.item(j).getNodeType() == Node.ELEMENT_NODE) { if("name".equals(childNodes.item(j).getNodeName())) { person.setName(childNodes.item(j).getFirstChild().getNodeValue()); } else if("age".equals(childNodes.item(j).getNodeName())) { person.setAge(Integer.parseInt(childNodes.item(j).getFirstChild().getNodeValue())); } } } list.add(person); } return list; } public static void main(String[] args) throws Exception { FileInputStream inputStream = new FileInputStream("C://test.xml"); DomXml domXml = new DomXml(); List<Person> list = domXml.getPersons(inputStream); for(Person person : list) { System.out.println(person.toString()); } } }
3)XMLPULL(org.xmlpull.v1) 方式
1) 新建一个项目,导入kxml2-2.2.2.jar包,创建一个描述信息Person类。
kxml2-2.2.2.jar包下载地址:http://download.csdn.net/detail/llping2010/6270791
public class Person { private String name; private int age; private int id; public Person() { // TODO Auto-generated constructor stub } public Person(String name, int age, int id) { super(); this.name = name; this.age = age; this.id = id; } /** * @return the name */ public String getName() { return name; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @return the age */ public int getAge() { return age; } /** * @param age the age to set */ public void setAge(int age) { this.age = age; } /** * @return the id */ public int getId() { return id; } /** * @param id the id to set */ public void setId(int id) { this.id = id; } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", id=" + id + "]"; } }
2) 创建一个PullXmlTools类,根据inputStream获取输入调用XmlPullParserFactoty解析XML将解析的数据保存到List<Person> list中返回。
public class PullXmlTools { public PullXmlTools() { // TODO Auto-generated constructor stub } public static List<Person> parseXml(InputStream inputStream, String encode) throws XmlPullParserException, IOException { List<Person> list = null; Person person = null; // 创建一个xml解析的工厂 XmlPullParserFactory xppFactovy = XmlPullParserFactory.newInstance(); // 获得xml解析类的引用 XmlPullParser parser = xppFactovy.newPullParser(); // 设置parser解析器的输入和编码类型 parser.setInput(inputStream, encode); int eventType = parser.getEventType(); while(eventType != XmlPullParser.END_DOCUMENT) { switch (eventType) { case XmlPullParser.START_DOCUMENT: list = new ArrayList<Person>(); break; case XmlPullParser.START_TAG: if("person".equals(parser.getName())) { person = new Person(); int id = Integer.parseInt(parser.getAttributeName(0)); person.setId(id); } else if("name".equals(parser.getName())) { String name = parser.nextText(); person.setName(name); } else if ("age".equals(parser.getName())) { int age = Integer.parseInt(parser.nextText()); person.setAge(age); } break; case XmlPullParser.END_TAG: if("person".equals(parser.getName())) { list.add(person); person = null; } break; } eventType = parser.getEventType(); } return list; } }
3) 定义一个测试类Test,读取文件FileInputStream调用PullXmlTools.parserXml()处理。
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
File file = new File("C://test.xml");
if(file.exists()) {
FileInputStream inputStream = new FileInputStream(file);
List<Person> list = PullXmlTools.parseXml(inputStream, "utf-8");
for(Person person : list) {
System.out.println(person.toString());
}
} else {
System.out.println("file is not exitst");
}
} catch (Exception e) {
// TODO: handle exception
}
}
}