【Android学习】XML文本的三种解析方式(通过搭建本地的Web项目提供XML文件)
XML为一种可扩展的标记语言,是一种简单的数据存储语言,使用一系列简单的标记来描述。
一、SAX解析
即Simple API for XML,以事件的形式通知程序,对Xml进行解析。
1、首先在Web项目中发布一个XML文档,名字为persons.xml,具体内容为:
<?xml version="1.0" encoding="UTF-8"?> <persons> <person id="1"> <name>周杰伦</name> <age>20</age> </person> <person id="2"> <name>小明</name> <age>21</age> </person> </persons>
2、SAX解析的流程主要如下:
通过创建SAXParserFactory对象获得一个实例,然后再通过工厂获得一个SaxParser,依靠SaxParser的parse方法,完成解析,其中parse方法的参数为一个InputStream类和一个DefaultHandler类,defaultHandler需 要重写
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser parse = spf.newSAXParser();
Myhandler handler = new Myhandler("person");
parse.parse(is, handler);
list = handler.getList();
3、重写处理类DefaultHandler。
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class Myhandler extends DefaultHandler { List<HashMap<String, String>> list = null;// 存储所有的解析对象 String currentTag = null; // 正在解析的标签 String currentValue = null; // 正在解析元素的值 String nodename = null; // 正在解析节点名称 HashMap<String, String> map = null;// 存储单个解析的完整对象 public Myhandler(String nodename) { this.nodename = nodename; } 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 endElement(String uri, String localName, String qName) throws SAXException { if (qName.equals(nodename)) { list.add(map); map = null; } super.endElement(uri, localName, qName); } @Override // 处理xml文件读取到的内容 public void characters(char[] ch, int start, int length) throws SAXException { if (currentTag != null && map != null) { currentValue = new String(ch, start, length); if (currentValue != null && !currentValue.trim().equals("") && !currentValue.trim().equals("\n")) { map.put(currentTag, currentValue); } } currentTag = null; currentValue = null; } }
4、通过自定义的HttpUtils类,从服务器获取数据,以流的形式返回,也就是XML文档的输入流,这里不再给出,关于获得服务器数据的三种方式下次会下次更新。
5、最后通过返回的List<Map<String,String>> 获得了XML文档的所需要的内容,需要提到的是,我在这里是需要解析person节点,于是只有qName等于person时候才会开始解析。
二、PULL解析
类似于SAX方式,程序以“拉取”的方式对Xml进行解析。
1、与SAX解析类似,但比SAX解析容易,需要JAR包,下载地址:
2、首先通过XMLPullFactory创建一个工厂,然后再由工厂创建一个XMLPullParser对象,由对象进行相关处理。
3、通过对eventType进行XML文件的节点解析,获得数据,并存放在List中进行返回。
import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; public class PullXmlHandler { public static List<Person> parseXml(InputStream is, String encode) throws Exception { List<Person> list = null; Person p = null; try { XmlPullParserFactory xmlPullF = XmlPullParserFactory.newInstance(); XmlPullParser parser = xmlPullF.newPullParser(); parser.setInput(is, 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 (parser.getName().equals("person")) { p = new Person(); if (parser.getAttributeCount() != 0) { p.setId(parser.getAttributeValue(0)); } } else if (parser.getName().equals("name")) { p.setName(parser.nextText()); } else if (parser.getName().equals("age")) { p.setAge(parser.nextText()); } break; case XmlPullParser.END_TAG: if (parser.getName().equals("person")) { list.add(p); p = null; } break; default: break; } //进行下次循环
eventType = parser.next(); } } catch (XmlPullParserException e) { // TODO Auto-generated catch block e.printStackTrace(); } return list; } }
三、DOM解析
“文档对象模型”方式,解析完的Xml将生成一个树状结构的对象。
1、DOM解析相对前两种比较麻烦,代码如下:
import java.io.InputStream; import java.util.ArrayList; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.xml.httputils.http_post; public class DomService { public DomService() { } public static List<Person> parseXML(InputStream is) throws Exception { List<Person> list = new ArrayList<Person>(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(is); // 获得节点 Element element = document.getDocumentElement(); NodeList nodeList = element.getElementsByTagName("person"); for (int i = 0; i < nodeList.getLength(); i++) { Element personElement = (Element) nodeList.item(i); Person p = new Person(); p.setId(personElement.getAttribute("id")); NodeList personList = personElement.getChildNodes(); for (int j = 0; j < personList.getLength(); j++) { if (personList.item(j).getNodeType() == Node.ELEMENT_NODE) { if ("name".equals(personList.item(j).getNodeName())) { p.setName(personList.item(j).getFirstChild() .getNodeValue()); } else if ("age".equals(personList.item(j).getNodeName())) { p.setAge(personList.item(j).getFirstChild() .getNodeValue()); } } } list.add(p); } return list; } public static void main(String[] args) throws Exception { DomService dom = new DomService(); List<Person> ps = dom.parseXML(http_post.getXMLStream()); for (Person p : ps) { System.out.println(p); } } }
总结:
对于小内存的设备,尤其是Android设备,使用PULL解析或者SAX解析远优于DOM解析。