在Android平台上可以使用Simple API for XML(SAX) 、 Document Object Model(DOM)和Android附带的pull解析器解析XML文件。
下面是本例子要解析的XML文件:itcast.xml
李明 30 李向梅 25
例子定义了一个javabean用于存放上面解析出来的xml内容, 这个javabean为Person,代码:
Person { Integer id; String name; Short age; Integer getId() { id; } setId(Integer id) { .id = id; } String getName() { name; } setName(String name) { .name = name; } Short getAge() { age; } setAge(Short age) { .age = age; } }
1. SAX解析XML文件
SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备。 SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,SAX会判断当前读到的字符是否合法XML语法中的某部分,如果符合就会触发事件。所谓事件,其实就是一些回调(callback)方法,这些方法(事件)定义在ContentHandler接口。
List<Person> readXML(InputStream inStream) { { SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser saxParser = spf.newSAXParser(); saxParser.setProperty("http://xml.org/sax/features/namespaces",);
XMLContentHandler handler = XMLContentHandler(); saxParser.parse(inStream, handler); inStream.close(); handler.getPersons(); } (Exception e) { e.printStackTrace(); } ; } XMLContentHandler DefaultHandler { List<Person> persons = ; Person currentPerson; String tagName = ; List<Person> getPersons() { persons; } @Override startDocument() SAXException { persons = ArrayList<Person>(); } @Override startElement(String namespaceURI, String localName, String qName, Attributes atts) SAXException { (localName.equals("person")){ currentPerson = Person(); currentPerson.setId(Integer.parseInt(atts.getValue("id"))); } .tagName = localName; } @Override characters([] ch, start, length) SAXException { (tagName!=){ String data = String(ch, start, length); (tagName.equals("name")){ .currentPerson.setName(data); } (tagName.equals("age")){ .currentPerson.setAge(Short.parseShort(data)); } } } @Override endElement(String uri, String localName, String name) SAXException { (localName.equals("person")){ persons.add(currentPerson); currentPerson = ; } .tagName = ; } }
2. DOM解析XML文件
DOM解析XML文件时,会将XML文件的所有内容读取到内存中,然后允许您使用DOM API遍历XML树、检索所需的数据。使用DOM操作XML的代码看起来比较直观,并且,在某些方面比基于SAX的实现更加简单。但是,因为DOM需要将XML文件的所有内容读取到内存中,所以内存的消耗比较大,特别对于运行Android的移动设备来说,因为设备的资源比较宝贵,所以建议还是采用SAX来解析XML文件,当然,如果XML文件的内容比较小采用DOM是可行的。
List<Person> readXML(InputStream inStream) { List<Person> persons = ArrayList<Person>(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); { DocumentBuilder builder = factory.newDocumentBuilder(); Document dom = builder.parse(inStream); Element root = dom.getDocumentElement(); NodeList items = root.getElementsByTagName("person"); ( i = 0; i < items.getLength(); i++) { Person person = Person(); Element personNode = (Element) items.item(i); person.setId( Integer(personNode.getAttribute("id"))); NodeList childsNodes = personNode.getChildNodes(); ( j = 0; j < childsNodes.getLength(); j++) { Node node = (Node) childsNodes.item(j); (node.getNodeType() == Node.ELEMENT_NODE){ Element childNode = (Element) node; ("name".equals(childNode.getNodeName())) { person.setName(childNode.getFirstChild().getNodeValue()); } (“age”.equals(childNode.getNodeName())) { person.setAge( Short(childNode.getFirstChild().getNodeValue())); } } } persons.add(person); } inStream.close(); } (Exception e) { e.printStackTrace(); } persons; }
3.Pull解析器解析XML文件
Pull解析器的运行方式与 SAX 解析器相似。它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。事件将作为数值代码被发送,因此可以使用一个switch对感兴趣的事件进行处理。当元素开始解析时,调用parser.nextText()方法可以获取下一个Text类型元素的值。
List<Person> readXML(InputStream inStream) { XmlPullParser parser = Xml.newPullParser(); { parser.setInput(inStream, "UTF-8"); eventType = parser.getEventType(); Person currentPerson = ; List<Person> persons = ; (eventType != XmlPullParser.END_DOCUMENT) { (eventType) { XmlPullParser.START_DOCUMENT: persons = ArrayList<Person>(); ; XmlPullParser.START_TAG: String name = parser.getName(); (name.equalsIgnoreCase("person")) { currentPerson = Person(); currentPerson.setId( Integer(parser.getAttributeValue(, "id"))); } (currentPerson != ) { (name.equalsIgnoreCase("name")) { currentPerson.setName(parser.nextText()); } (name.equalsIgnoreCase("age")) { currentPerson.setAge( Short(parser.nextText())); } } ; XmlPullParser.END_TAG: (parser.getName().equalsIgnoreCase("person") && currentPerson != ) { persons.add(currentPerson); currentPerson = ; } ; } eventType = parser.next(); } inStream.close(); persons; } (Exception e) { e.printStackTrace(); } ; } String writeXML(List<Person> persons, Writer writer){ XmlSerializer serializer = Xml.newSerializer(); { serializer.setOutput(writer); serializer.startDocument("UTF-8", ); serializer.startTag("", "persons"); (Person person : persons){ serializer.startTag("", "person"); serializer.attribute("", "id", person.getId().toString()); serializer.startTag("", "name"); serializer.text(person.getName()); serializer.endTag("", "name"); serializer.startTag("", "age"); serializer.text(person.getAge().toString()); serializer.endTag("", "age"); serializer.endTag("", "person"); } serializer.endTag("", "persons"); serializer.endDocument(); writer.toString(); } (Exception e) { e.printStackTrace(); } ; } File xmlFile = File("myitcast.xml"); FileOutputStream outStream = FileOutputStream(xmlFile); OutputStreamWriter outStreamWriter = OutputStreamWriter(outStream, "UTF-8"); BufferedWriter writer = BufferedWriter(outStreamWriter); writeXML(persons, writer); writer.flush(); writer.close(); StringWriter writer = StringWriter(); writeXML(persons, writer); String content = writer.toString();
4.SAX和PULL使用
区别为:SAX解析器的工作方式是自动将事件推入事件处理器进行处理,因此你不能控制事件的处理主动结束;而Pull解析器的工作方式为允许你的应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。
你随便找个sax和pull的例子比较一下就可以发现,pull是一个while循环,随时可以跳出,而sax不是,sax是只要解析了,就必须解析完成。