一、理论准备
SAX采用事件驱动机制来解析XML文档,每当SAX解析器发现文档开始、元素开始、文本、元素结束、文档结束等事件时,就会向外发送一次事件,而开发者则可以通过编写事件监听器处理这些事件,以此来获取XML文档里的信息。
DOM标准简单易用,但是它需要一次性地读取整个XML文档,而且在程序运行期间,整个DOM树常驻内存,导致系统开销过大。SAX解析方式占用内存小,处理速度更快。
由于DOM一次性将整个XML文档全部读入内存,因此可以随机访问XML文档的每个元素。SAX采用顺序模式来依次读取XML文档,因此无法做到随机访问XML文档的任意元素。
二、项目结构
三、实例实现
<?xml version="1.0" encoding="UTF-8"?> Jack24Tom25Bob22
ps:不知道为啥,用xml格式发布就出问题,用java就不出问题~~
package xml; import java.io.InputStream; import java.util.List; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; public class SaxService { public static List readXML(InputStream inputStream) throws Exception { SAXParserFactory spf = SAXParserFactory.newInstance(); //创建SAXParserFactory对象(SAX解析器工厂) SAXParser saxParser = spf.newSAXParser(); //创建SAXParser对象(SAX解析器) MyDefaultHandle myDefaultHandle = new MyDefaultHandle(); //MyDefaultHandle对象,继承自DefaultHandle类 saxParser.parse(inputStream, myDefaultHandle); //解析XML文档(以InputStream对象的形式) inputStream.close(); //关闭InputStream对象 return myDefaultHandle.getPersonList(); //返回XML文档中的数据列表 } }
package xml; import java.util.ArrayList; import java.util.List; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class MyDefaultHandle extends DefaultHandler { private Person person = null; //存储解析得到的单个Person对象 private List personList = null; //存储解析得到的所有Person对象 private String currentTag = null; //正在解析的元素的标签 private static final String TAG = "MyDefaultHandle"; //Log标签 public List getPersonList() { return personList; } public void startDocument() throws SAXException { personList = new ArrayList(); System.out.println("开始解析"); } public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if(qName.equals("person")) { //当遇到标签时,创建一个Person对象 person = new Person(); if(attributes!=null) { person.setId(Integer.parseInt(attributes.getValue(0)));//将读到的id属性值存入Person对象 } System.out.println("处理标签"); } currentTag = qName; //设置当前读到的标签 } public void characters(char[] ch, int start, int length) throws SAXException { String currentValues = new String(ch, start, length); //获取当前标签里的内容 if(currentTag != null) { if(currentTag.equals("name")) { //将读到的name属性值存入Person对象 person.setName(currentValues); }else if(currentTag.equals("age")) { //将读到的age属性值存入Person对象 person.setAge(Integer.parseInt(currentValues)); } System.out.println("处理元素"); } } public void endElement(String uri, String localName, String qName) throws SAXException { //当读到标签时,向列表中添加读取到的单个Person对象 if(qName.equals("person") && (person != null)) { personList.add(person); person = null; System.out.println("添加一个person"); } currentTag = null; } public void endDocument() throws SAXException { System.out.println("完毕"); } }
package xml; public class Person { private String name; private int age; private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
package xml;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
public class Test {
static String URL_PATH = "http://localhost:8080/TestGet/person.xml";
public static InputStream getInputStream() throws IOException {
InputStream inputStream = null;
HttpURLConnection httpURLConnection = null;
try {
URL url = new URL(URL_PATH);
if (url != null) {
httpURLConnection = (HttpURLConnection) url.openConnection();
// 设置连接网络的超时时间
httpURLConnection.setConnectTimeout(3000);
httpURLConnection.setDoInput(true);
// 设置本次http请求使用get方式请求
httpURLConnection.setRequestMethod("GET");
int responseCode = httpURLConnection.getResponseCode();
if (responseCode == 200) {
// 从服务器获得一个输入流
inputStream = httpURLConnection.getInputStream();
}
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return inputStream;
}
public static void main(String[] args) throws IOException, Exception {
// TODO Auto-generated method stub
if(getInputStream()==null) {
System.out.println("读取失败");
return ;
}
List<Person> person = SaxService.readXML(getInputStream());
System.out.println(person.size());
for(int i=0; i<person.size(); i++)
System.out.println("id:"+person.get(i).getId()+"age:"+person.get(i).getAge()
+"name:"+person.get(i).getName());
}
}
结果如下:
开始解析 处理元素 处理标签 处理元素 处理元素 处理元素 添加一个person 处理标签 处理元素 处理元素 处理元素 添加一个person 处理标签 处理元素 处理元素 处理元素 添加一个person 完毕 3 id:1age:24name:Jack id:2age:25name:Tom id:3age:22name:Bob
四、遗留问题
1.sax解析中Name和localName什么区别,想到这个是因为一哥们用的localName和person判断他表示结果对了,费解???
2.endElement的if里把person设置为null是为了防止重复触发该事件,之后把currentTag设置为null是何意?莫非存在如下情况,费解啊。。。