XML解析
1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.util.ArrayList; 6 import java.util.List; 7 8 import javax.xml.*; 9 import javax.xml.parsers.DocumentBuilder; 10 import javax.xml.parsers.DocumentBuilderFactory; 11 import javax.xml.parsers.SAXParser; 12 import javax.xml.parsers.SAXParserFactory; 13 import javax.xml.transform.sax.SAXTransformerFactory; 14 15 import org.w3c.dom.Document; 16 import org.w3c.dom.NamedNodeMap; 17 import org.w3c.dom.Node; 18 import org.w3c.dom.NodeList; 19 import org.xml.sax.Attributes; 20 import org.xml.sax.SAXException; 21 import org.xml.sax.helpers.DefaultHandler; 22 /*XML文件 23 <?xml version="1.0" encoding="UTF-8"?> 24 <users> 25 <user id="01"> id为属性 name为元素 26 <name>张三</name> 27 <age>15</age> 28 </user> 29 <user id="02"> 30 <name>李四</name> 31 <age>15</age> 32 </user> 33 </users> 34 以下三种解析方法中的User为自定义类,用来接收对象的值 35 XML是一个以文本来描述数据的文档 36 SAX表现较好,这要依赖于它特定的解析方式。一个SAX 检测即将到来的XML流,但并 37 没有载入到内存(当然当XML流被读入时,会有部分文档暂时隐藏在内存中)。 38 DOM的优点,由于树在内存中是持久的,因此可以修改后更新。它还可以在任何时候在树 39 中上下导航,API使用起来也较简单。 40 */ 41 public class XMLParser { 42 private String id; 43 private String name; 44 private String age; 45 public static void main(String[] args) throws Exception { 46 List<User> list=new XMLParser().XMLParser_SAX(); 47 System.out.println(list); 48 } 49 //XML解析方法之:DOM:将整个文档树在内存中,便于操作,支持删除,修改,重新排列等多种功能,但占内存 50 public List<User> parserDom() throws Exception{ 51 ArrayList<User> list=new ArrayList<User>();//存放解析的数据 52 User user=null; 53 DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();//创建一个文件建筑工厂 54 DocumentBuilder builder= factory.newDocumentBuilder();//创建一个建筑者 55 InputStream is=new FileInputStream("E:\\学习文件\\Android文件\\eclipse代码\\work_space\\XML_parser\\src\\users.xml"); 56 Document parse = builder.parse(is);//创建一个解析器, 也可以传入一个流对象,从而利用转换流指定编码格式 57 NodeList nodes = parse.getElementsByTagName("user");//解析user 58 for(int i=0;i<nodes.getLength();i++){ 59 NamedNodeMap map = nodes.item(i).getAttributes();//获取装属性的集合(如id) 60 user=new User();//存放用户信息 61 for(int j=0;j<map.getLength();j++){//当属性有多个值的时候就可以这样解析 62 if(map.item(j).getNodeName().equals("id")){//获得属性的名字 63 id=map.item(j).getNodeValue();//获得属性的值 64 user.setId(id); 65 } 66 } 67 NodeList childNodes = nodes.item(i).getChildNodes();//获取子节点(装元素的集合) 68 for(int k=0;k<childNodes.getLength();k++){ 69 String nodeName = childNodes.item(k).getNodeName(); 70 if(nodeName.equals("name")){ 71 name=childNodes.item(k).getTextContent();//获取元素值 72 user.setName(name); 73 }else if(nodeName.equals("age")){ 74 age=childNodes.item(k).getTextContent(); 75 user.setAge(age); 76 } 77 } 78 list.add(user); 79 user=null;//避免数据存放出错 80 } 81 return list; 82 } 83 //XML解析方法之:SAX:不用事先调入整个文档,占用资源少 ,一行行解析的 84 public List<User> XMLParser_SAX() throws Exception{ 85 SAXParserFactory factory = SAXParserFactory.newInstance(); 86 SAXParser parser = factory.newSAXParser(); 87 InputStream is=new FileInputStream("E:\\学习文件\\Android文件\\eclipse代码\\work_space\\XML_parser\\src\\users.xml"); 88 UserHandler handler=new UserHandler(); 89 parser.parse(is, handler); 90 List<User> list = handler.getUser(); 91 return list; 92 } 93 class UserHandler extends DefaultHandler{//SAX解析方式的需要 94 ArrayList<User> list;//存放解析的数据 95 User user=null; 96 String flag;//用来标记解析的是哪个属性或元素 97 public void startDocument() throws SAXException { 98 System.out.println("开始解析"); 99 } 100 public void endDocument() throws SAXException { 101 System.out.println("解析结束"); 102 } 103 public void startElement(String uri, String localName, String qName, 104 Attributes attributes) throws SAXException { 105 //解析这样的语句:<users> <user> <name> <age>的时候回调此方法 106 if(qName.equals("users")){ 107 list=new ArrayList<User>(); 108 }else if(qName.equals("user")){ 109 user=new User();//没解析一个用户就创建一个对象 110 user.setId(attributes.getValue("id"));//获取属性id的值 111 }else{ 112 flag=qName;//得到解析的是哪个元素 113 } 114 } 115 //解析这样的语句:</users> </user> </name>的时候回调此方法 116 public void endElement(String uri, String localName, String qName) 117 throws SAXException { 118 if(qName.equals("user")){ 119 list.add(user);//解析完一个就添加且清除 120 user=null; 121 } 122 } 123 //解析元素和属性的时候回调此方法 124 public void characters(char[] ch, int start, int length) 125 throws SAXException { 126 if(flag!=null){//在解析属性的时候为空 127 if(flag.equals("name")){ 128 user.setName(new String(ch,start,length)); 129 }else if(flag.equals("age")){ 130 user.setAge(new String(ch,start,length)); 131 } 132 } 133 flag=null;//没有这句,数据就会出错,很多空格 134 } 135 public List<User> getUser(){//提供一方法返回解析数据 136 return list; 137 } 138 } 139 } 140 //XML解析第三种方法:PUll需要下载这个包:org.xmlpull.v1
解析图解
说明:解析到哪条执行相对应的方法 下图数字代码对应的编码
存放数据的User类
1 public class User { 2 private String id; 3 private String name; 4 private String age; 5 public String getId() { 6 return id; 7 } 8 public void setId(String id) { 9 this.id = id; 10 } 11 public String getName() { 12 return name; 13 } 14 public void setName(String name) { 15 this.name = name; 16 } 17 public String getAge() { 18 return age; 19 } 20 public void setAge(String age) { 21 this.age = age; 22 } 23 @Override 24 public String toString() { 25 return "User [id=" + id + ", name=" + name + ", age=" + age + "]"; 26 } 27 28 }
PULL解析XML文件例子:需要的包名:kxml2-2.2.2.jar
解析的XML文件:
<?xml version="1.0" encoding="gbk"?> <students> <student id="1001"> <name>夏志明</name> <age>18</age> <sex>男</sex> <books> <book> <name>十万个为什么</name> <author>匿名</author> <price>100</price> </book> <book> <name>平凡的世界</name> <author>路遥</author> <price>200</price> </book> <book> <name>人生</name> <author>路遥</author> <price>100</price> </book> </books> </student> <student id="1002"> <name>方高</name> <age>18</age> <sex>女</sex> <books> <book> <name>java开发大全</name> <author>李刚</author> <price>100</price> </book> <book> <name>人生</name> <author>路遥</author> <price>100</price> </book> </books> </student> </students>
java代码:
package com.mobiletrain.pull02; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; /* * pull解析注意: parser.nextText()代表下一个内容 parser.next()代表下一个节点 得到标签的属性名称 (如:student id="1001" id就为属性) String att = parser.getAttributeName(0); 得到标签的属性的值 String value = parser.getAttributeValue(0); */ public class Test { public static void main(String[] args) { try { // 1,创建解析器工厂对象 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); // 2,由解析器工厂对象创建解析器对象 XmlPullParser parser = factory.newPullParser(); // 3,设置数据源 parser.setInput(new FileReader("students.xml")); // 4,得到事件码 int code = parser.getEventType(); List<Student> students = null; Student student = null; List<Book> books = null; Book book = null; String nowTag = null; while (code != 1) { String name = parser.getName();// 得到节点的名称 switch (code) { case 2: if ("students".equals(name)) { students = new ArrayList<Student>(); } else if ("student".equals(name)) { student = new Student(); nowTag = "学生"; // 得到Student的属性名称 // String att = parser.getAttributeName(0); // 得到Student标签的属性的值 String value = parser.getAttributeValue(0); student.setId(Integer.parseInt(value)); } else if ("name".equals(name) && "学生".equals(nowTag)) { student.setName(parser.nextText()); } else if ("age".equals(name)) { student.setAge(Integer.parseInt(parser.nextText())); } else if ("sex".equals(name)) { student.setSex(parser.nextText()); } else if ("books".equals(name)) { books = new ArrayList<Book>(); } else if ("book".equals(name)) { book = new Book(); nowTag = "书"; } else if ("name".equals(name) && "书".equals(nowTag)) { book.setName(parser.nextText()); } else if ("author".equals(name)) { book.setAuthor(parser.nextText()); } else if ("price".equals(name)) { book.setPrice(Integer.parseInt(parser.nextText())); } break; case 3: if ("book".equals(name)) { books.add(book); } else if ("books".equals(name)) { student.setList(books); } else if ("student".equals(name)) { students.add(student); } break; default: break; } // 解析下一个节点 code = parser.next();// 得到下一个节点的事件码 } for (Student student2 : students) { System.out.println(student2); } } catch (Exception e) { e.printStackTrace(); } } }
存放数据的类:
package com.mobiletrain.pull02; import java.util.List; public class Student { private int id; private String name; private String sex; private int age; private List<Book> list; public void setId(int id) { this.id = id; } public void setName(String name) { this.name = name; } public void setSex(String sex) { this.sex = sex; } public void setAge(int age) { this.age = age; } public void setList(List<Book> list) { this.list = list; } @Override public String toString() { return "Student [id=" + id + ", name=" + name + ", sex=" + sex + ", age=" + age + ", list=" + list + "]\n"; } }
注意点:
1.xml属性要打双引号
2.当解析的文件源是字符串而不是一个文件的时候(当使用网络下载数据保存到字符串上时:)
String xml = HttpUtils.getXMLByInternet("http://weather.xcyh.org/xml/7");//自定义的下载工具 将xml数据下载到字符串中 // 解析xml数据 // 创建解析器工厂对象 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); // 2,创建解析器对象 XmlPullParser parser = factory.newPullParser(); // 3,设置数据源 // StringReader 是Reader的子类 // StringReader 的数据源是String类型的字符串 parser.setInput(new StringReader(xml)); //当这里是数据源是文件的时候就是 new FileReader("xml文件路径"); // 4,得到事件码 int code = parser.getEventType();