1 <?xml version="1.0" encoding="UTF-8"?>
2 <persons>
3 <person id="23">
4 <name>jack</name>
5 <age>30</age>
6 </person>
7 <person id="20">
8 <name>rose</name>
9 <age>25</age>
10 </person>
11 </persons>
Android中,常见的XML解析器分别为:
SAX解析器:SAX(org.xml.sax)Simple API for XML,以事件的形式通知程序,对Xml进行解析。
DOM解析器:DOM(org.w3c.dom)“文档对象模型”方式,解析完的Xml将生成一个树状结构的对象。(不推荐)
PULL解析器:XMLPULL(org.xmlpull.v1)类似于SAX方式,程序以“拉取”的方式对Xml进行解析。
---------------------
SAX解析器:是一种以事件驱动的XML api,由它定义的事件流可以指定从解析器传到专门的处理程序的代码的XML结构,
简单的讲,它解析速度快,占用内存少的解析器。这种解析器比较适合android 等移动设备。
1 定义变量:存储单个解析的完整对象HashMap<String, String> map
存储所有的解析对象 List<HashMap<String,String>> list
正在解析的元素的标签 String currentTag=null;
解析当前元素的值 String currentVal=null;
解析当前节点名称String nodeName=null;
并为list对象生成get方法和在构造方法中传递正在解析的节点名称
2.完成方法:
3.定义service 创建SAXParserFactory对象 SAXParser对象来解析xml,通过定义的list的get方法返回
4.定义http工具类 返回xml从服务器返回的输入流
5.建立测试类 指定网络路径
myHandler.java
1 package com.sax.handler; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.List; 6 7 import org.xml.sax.Attributes; 8 import org.xml.sax.SAXException; 9 import org.xml.sax.helpers.DefaultHandler; 10 11 12 13 public class myHandler extends DefaultHandler{ 14 15 private HashMap<String, String> map=null;//存储单个解析的完整对象 16 private List<HashMap<String,String>> list=null;//存储所有的解析对象 17 private String currentTag=null;//正在解析的元素的标签 18 private String currentVal=null;//解析当前元素的值 19 private String nodeName=null;//解析当前节点名称 20 21 public List<HashMap<String, String>> getList() { 22 return list; 23 } 24 25 public myHandler(String nodeName) { 26 // TODO Auto-generated constructor stub 27 this.nodeName=nodeName; 28 } 29 30 //解析到开始文档 31 //当读到第一个开始标签的时候会触发这个方法 32 @Override 33 public void startDocument() throws SAXException { 34 // TODO Auto-generated method stub 35 System.out.println("--startDocument()--"); 36 list=new ArrayList<HashMap<String,String>>(); 37 } 38 39 //开始元素 40 //当遇到文档开头的时候会调用这个方法 41 @Override 42 public void startElement(String uri, String localName, String qname,Attributes attributes) throws SAXException { 43 // TODO Auto-generated method stub 44 //判断正在解析的元素是不是开始解析的元素 45 System.out.println("--startElement()--"+qname); 46 if(qname.equals(nodeName)){ 47 map=new HashMap<String, String>(); 48 } 49 if(attributes!=null&&map!=null){ 50 for (int i = 0; i < attributes.getLength(); i++) { 51 map.put(attributes.getQName(i), attributes.getValue(i)); 52 } 53 } 54 System.out.println(qname+":"+map); 55 currentTag=qname; 56 } 57 58 //元素内容 59 //用来处理xml文件所读取到的内容 60 @Override 61 public void characters(char[] ch, int start, int length) throws SAXException { 62 // TODO Auto-generated method stub 63 if(currentTag!=null&&map!=null){ 64 currentVal=new String(ch,start,length); 65 if(currentVal!=null&&!currentVal.trim().equals("")&&!currentVal.trim().equals(" ")){ 66 map.put(currentTag, currentVal); 67 } 68 } 69 System.out.println("--characters()--"+currentTag+" "+currentVal); 70 currentTag=null;//把当前节点对应标签和值设空 71 currentVal=null; 72 } 73 74 75 //结束解析 76 //遇到结束标记的时候会调用这个方法 77 @Override 78 public void endElement(String uri, String localName, String qName) 79 throws SAXException { 80 // TODO Auto-generated method stub 81 System.out.println("--endElement()--"+qName); 82 if(qName.equals(nodeName)){ 83 list.add(map); 84 map=null; 85 } 86 } 87 88 //结束解析文档 89 90 //结束解析文档,即解析根元素结束标签时调用该方法 91 @Override 92 public void endDocument() throws SAXException { 93 // TODO Auto-generated method stub 94 System.out.println("--endDocument()--"); 95 super.endDocument(); 96 } 97 }
httpUtils.java
1 package com.sax.http; 2 3 import java.io.InputStream; 4 import java.net.HttpURLConnection; 5 import java.net.URL; 6 7 public class httpUtils { 8 public httpUtils (){ 9 10 } 11 public static InputStream getXml(String path){ 12 InputStream inputStream=null; 13 try { 14 URL url=new URL(path); 15 if(url!=null){ 16 HttpURLConnection connection=(HttpURLConnection)url.openConnection(); 17 connection.setConnectTimeout(3000); 18 connection.setDoInput(true); 19 connection.setRequestMethod("GET"); 20 int code=connection.getResponseCode(); 21 if(code==200){ 22 inputStream=connection.getInputStream(); 23 } 24 25 } 26 } catch (Exception e) { 27 // TODO: handle exception 28 } 29 return inputStream; 30 } 31 }
saxService.java
1 package com.sax.service; 2 3 import java.io.InputStream; 4 import java.util.HashMap; 5 import java.util.List; 6 7 import javax.xml.parsers.SAXParser; 8 import javax.xml.parsers.SAXParserFactory; 9 10 import com.sax.handler.myHandler; 11 12 public class saxService { 13 14 public saxService() { 15 // TODO Auto-generated constructor stub 16 } 17 public static List<HashMap<String,String>> readXml(InputStream inputStream,String nodeName){ 18 try { 19 SAXParserFactory spf=SAXParserFactory.newInstance();//创建解析工厂对象 20 SAXParser parser=spf.newSAXParser();//用来解析xml 21 myHandler handler=new myHandler(nodeName); 22 parser.parse(inputStream,handler); 23 inputStream.close(); 24 return handler.getList(); 25 } catch (Exception e) { 26 // TODO: handle exception 27 } 28 return null; 29 } 30 31 }
test.java
1 package com.sax.test; 2 3 import java.io.InputStream; 4 import java.util.ArrayList; 5 import java.util.HashMap; 6 import java.util.List; 7 import java.util.Map; 8 9 import com.sax.http.httpUtils; 10 import com.sax.service.saxService; 11 12 public class test { 13 14 /** 15 * @param args 16 */ 17 public static void main(String[] args) { 18 // TODO Auto-generated method stub 19 String path="http://122.206.79.193:8080/myhttp/person.xml"; 20 InputStream inputStream=httpUtils.getXml(path); 21 try { 22 List<HashMap<String,String>> list=saxService.readXml(inputStream, "person"); 23 for(HashMap<String,String> map:list){ 24 System.out.println(map.toString()); 25 } 26 } catch (Exception e) { 27 // TODO: handle exception 28 } 29 } 30 31 }
---------------------------------
XmlPull:
和Sax类似,是基于流(stream)操作文件,然后根据节点事件回调开发者编写的处理程序。
因为是基于流的处理,因此Xmlpull和 Sax都比较节约内存资源,不会象Dom那样要把所有节点以对橡树的形式展现在内存中。 但Xmlpull比Sax更简明,而且不需要扫描完整个流。
1 package com.xml.domain; 2 3 public class person { 4 5 private int id; 6 private String name; 7 private int age; 8 public int getId() { 9 return id; 10 } 11 public void setId(int id) { 12 this.id = id; 13 } 14 public String getName() { 15 return name; 16 } 17 @Override 18 public String toString() { 19 return "person [id=" + id + ", name=" + name + ", age=" + age + "]"; 20 } 21 public person(int id, String name, int age) { 22 super(); 23 this.id = id; 24 this.name = name; 25 this.age = age; 26 } 27 public void setName(String name) { 28 this.name = name; 29 } 30 public int getAge() { 31 return age; 32 } 33 public void setAge(int age) { 34 this.age = age; 35 } 36 public person() { 37 // TODO Auto-generated constructor stub 38 } 39 40 }
httpUtils
1 package com.xml.http; 2 3 import java.io.InputStream; 4 import java.net.HttpURLConnection; 5 import java.net.URL; 6 7 public class httpUtils { 8 public httpUtils (){ 9 10 } 11 public static InputStream getXml(String path){ 12 InputStream inputStream=null; 13 try { 14 URL url=new URL(path); 15 if(url!=null){ 16 HttpURLConnection connection=(HttpURLConnection)url.openConnection(); 17 connection.setConnectTimeout(3000); 18 connection.setDoInput(true); 19 connection.setRequestMethod("GET"); 20 int code=connection.getResponseCode(); 21 if(code==200){ 22 inputStream=connection.getInputStream(); 23 } 24 25 } 26 } catch (Exception e) { 27 // TODO: handle exception 28 } 29 return inputStream; 30 } 31 }
pullXmlTools
1 package com.xml.pull; 2 3 import java.io.InputStream; 4 import java.util.ArrayList; 5 import java.util.List; 6 7 import org.xmlpull.v1.XmlPullParser; 8 import org.xmlpull.v1.XmlPullParserException; 9 import org.xmlpull.v1.XmlPullParserFactory; 10 11 import com.xml.domain.person; 12 13 /** 14 * 记得导入包 15 * @author Administrator 16 * 优点:比sax简单 17 * 缺点:swtich时需要知道节点名称 18 * 19 */ 20 public class pullXmlTools { 21 22 public pullXmlTools() { 23 // TODO Auto-generated constructor stub 24 } 25 //inputStream:从服务器获取xml,以流的形式返回 26 public static List<person> parseXml(InputStream inputStream,String encode) throws Exception{ 27 List<person> list=null; 28 person person=null;//装载解析的每个节点的内容 29 //创建xml工厂 30 XmlPullParserFactory factory=XmlPullParserFactory.newInstance(); 31 //获得解析类 32 XmlPullParser parser= factory.newPullParser(); 33 parser.setInput(inputStream, encode); 34 //获得事件的类型 35 int eventType=parser.getEventType(); 36 while(eventType!=XmlPullParser.END_DOCUMENT){ 37 switch (eventType) { 38 case XmlPullParser.START_DOCUMENT: 39 list=new ArrayList<person>(); 40 break; 41 case XmlPullParser.START_TAG: 42 if("person".equals(parser.getName())){ 43 person=new person(); 44 int id=Integer.parseInt(parser.getAttributeValue(0)); 45 person.setId(id); 46 } 47 else if("name".equals(parser.getName())){ 48 String name=parser.nextText();//获取该节点的内容 49 person.setName(name); 50 } 51 else if("age".equals(parser.getName())){ 52 int age=Integer.parseInt(parser.nextText()); 53 person.setAge(age); 54 } 55 list=new ArrayList<person>(); 56 break; 57 case XmlPullParser.END_TAG: 58 if("person".equals(parser.getName())){ 59 list.add(person); 60 person=null; 61 } 62 break; 63 } 64 eventType=parser.next();//循环 65 } 66 return list; 67 68 } 69 }
test
1 package com.xml.test; 2 3 import java.io.InputStream; 4 import java.util.List; 5 6 import com.xml.domain.person; 7 import com.xml.http.httpUtils; 8 import com.xml.pull.pullXmlTools; 9 10 11 12 public class Test { 13 14 public Test() { 15 // TODO Auto-generated constructor stub 16 } 17 18 /** 19 * @param args 20 * @throws Exception 21 */ 22 public static void main(String[] args) throws Exception { 23 // TODO Auto-generated method stub 24 String path="http://122.206.79.193:8080/myhttp/person.xml"; 25 InputStream inputStream=httpUtils.getXml(path); 26 List<person> list=pullXmlTools.parseXml(inputStream, "UTF-8"); 27 for (person person : list) { 28 System.out.println(person.toString()); 29 } 30 } 31 32 }
-------------------------------
优点:a、由于整棵树在内存中,因此可以对xml文档随机访问
b、可以对xml文档进行修改操作
c、较sax,dom使用也更简单。
缺点:a、整个文档必须一次性解析完
b、由于整个文档都需要载入内存,对于大文档成本高
1 package com.xml.dom.domain; 2 3 public class person { 4 5 private int id; 6 private String name; 7 private int age; 8 public int getId() { 9 return id; 10 } 11 public void setId(int id) { 12 this.id = id; 13 } 14 public String getName() { 15 return name; 16 } 17 @Override 18 public String toString() { 19 return "person [id=" + id + ", name=" + name + ", age=" + age + "]"; 20 } 21 public person(int id, String name, int age) { 22 super(); 23 this.id = id; 24 this.name = name; 25 this.age = age; 26 } 27 public void setName(String name) { 28 this.name = name; 29 } 30 public int getAge() { 31 return age; 32 } 33 public void setAge(int age) { 34 this.age = age; 35 } 36 public person() { 37 // TODO Auto-generated constructor stub 38 } 39 40 }
http
1 package com.xml.dom.http; 2 3 import java.io.InputStream; 4 import java.net.HttpURLConnection; 5 import java.net.URL; 6 7 public class httpUtils { 8 public httpUtils (){ 9 10 } 11 public static InputStream getXml(String path){ 12 InputStream inputStream=null; 13 try { 14 URL url=new URL(path); 15 if(url!=null){ 16 HttpURLConnection connection=(HttpURLConnection)url.openConnection(); 17 connection.setConnectTimeout(3000); 18 connection.setDoInput(true); 19 connection.setRequestMethod("GET"); 20 int code=connection.getResponseCode(); 21 if(code==200){ 22 inputStream=connection.getInputStream(); 23 } 24 25 } 26 } catch (Exception e) { 27 // TODO: handle exception 28 } 29 return inputStream; 30 } 31 }
dom
1 package com.xml.dom.service; 2 3 import java.io.InputStream; 4 import java.util.ArrayList; 5 import java.util.List; 6 7 import javax.xml.parsers.DocumentBuilder; 8 import javax.xml.parsers.DocumentBuilderFactory; 9 import javax.xml.parsers.ParserConfigurationException; 10 11 import org.w3c.dom.Document; 12 import org.w3c.dom.Element; 13 import org.w3c.dom.Node; 14 import org.w3c.dom.NodeList; 15 16 import com.xml.dom.domain.person; 17 18 public class DomService { 19 20 public DomService() { 21 // TODO Auto-generated constructor stub 22 } 23 24 public List<person> getPersons(InputStream inputStream) throws Exception{ 25 List<person> list=new ArrayList<person>(); 26 DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();//创建dom解析工厂 27 DocumentBuilder builder=factory.newDocumentBuilder();// 28 Document dom=builder.parse(inputStream);//得到文档对象 29 Element element=dom.getDocumentElement();//获得稳定的元素节点 30 NodeList personNodes=element.getElementsByTagName("person");//从person节点开始遍历 31 for (int i = 0; i < personNodes.getLength(); i++) { 32 Element personElement=(Element)personNodes.item(i); 33 person person=new person(); 34 person.setId(Integer.parseInt(personElement.getAttribute("id"))); 35 NodeList childNodes=personElement.getChildNodes();//该节点的所有属性 36 for (int j = 0; j < childNodes.getLength(); j++) { 37 if(childNodes.item(j).getNodeType()==Node.ELEMENT_NODE){ 38 if("name".equals(childNodes.item(j).getNodeName())){ 39 person.setName(childNodes.item(j).getFirstChild().getNodeValue()); 40 } 41 else if("age".equals(childNodes.item(j).getNodeName())){ 42 person.setAge(Integer.parseInt(childNodes.item(j).getFirstChild().getNodeValue())); 43 } 44 } 45 } 46 list.add(person); 47 } 48 return list; 49 } 50 51 52 }
test
1 package com.xml.dom.test; 2 3 import java.io.InputStream; 4 import java.util.ArrayList; 5 import java.util.HashMap; 6 import java.util.List; 7 import java.util.Map; 8 9 import com.xml.dom.domain.person; 10 import com.xml.dom.http.httpUtils; 11 import com.xml.dom.service.DomService; 12 13 14 15 public class test { 16 17 /** 18 * @param args 19 */ 20 public static void main(String[] args) { 21 // TODO Auto-generated method stub 22 String path="http://122.206.79.193:8080/myhttp/person.xml"; 23 InputStream inputStream=httpUtils.getXml(path); 24 try { 25 DomService domService=new DomService(); 26 List<person>list= domService.getPersons(inputStream); 27 for(person person:list){ 28 System.out.println(person.toString()); 29 } 30 } catch (Exception e) { 31 // TODO: handle exception 32 } 33 } 34 35 }
三种方式的对比:
方式 | 是否提供服务器端jsonString的生成方法 | 优缺点 |
SAX |
首先创建自己的事件处理器类myHandler:myHandler extends DefaultHandler 其次,建立httpUtils,从服务器读取xml文件并返回读入流 第三,实例化工厂、解析对象和事件处理对象,通过使用解析器的解析方法对输入流进行解析,并通过时间处理器的get方法返回最终的结果 SAXParserFactory spf=SAXParserFactory.newInstance();//创建解析工厂对象 |
完美 |
PULL | 需要导入第三方的kxml2-2.2.2.jar
首先需要建立一个解析xml的方法,该方法有两个传入参数,InputStream inputStream,String encode 其次,建立httpUtils,从服务器读取xml文件并返回读入流 第三,完善第一步的方法:实例化工厂、解析对象,将输入流和编码方式设置给解析对象并通过解析器parser.getEventType()方法获得标签类型, while+switch方式遍历整个文档标签,获取相应的参数、对象并累加返回list person person=null;//装载解析的每个节点的内容//创建xml工厂 |
优点:简单 缺点:需要提前知道各个节点的名字 |
DOM |
首先需要建立一个解析xml的方法,该方法有两个传入参数,InputStream inputStream 其次,建立httpUtils,从服务器读取xml文件并返回读入流 第三,完善第一步的方法:实例化工厂、解析对象,将输入流设置给解析对象builder.parse(inputStream)获取文档对象, 然后通过文档对象的getDocumentElement方法获取稳定节点,然后遍历 DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();//创建dom解析工厂 |
缺点:有撑破内存的可能,极不推荐 |
---------------------------------
xml序列化:
1 public void xml(View view){ 2 //初始化序列化器 3 XmlSerializer serializer= Xml.newSerializer(); 4 File file=new File(Environment.getExternalStorageDirectory(),"xml.xml"); 5 FileOutputStream os=new FileOutputStream(file); 6 serializer.setOutput(os, "utf-8"); 7 8 serializer.startDocument("utf-8", true);//开头 9 serializer.startTag(null, "persons"); 10 for(Person ps:PersonList){ 11 serializer.startTag(null, "person"); 12 serializer.attribute(null, "id", ps.getId()); 13 14 serializer.startTag(null, "age"); 15 serializer.text( ps.getname()); 16 serializer.endTag(null, "age"); 17 18 serializer.endTag(null, "person"); 19 } 20 serializer.endTag(null, "persons"); 21 serializer.endDocument();//结尾 22 }