由于SAX解析XML的方式优缺点已经在网上随处可见,此博客只记录一下用法。
第一步:
编写一个XML文件,名为people.xml,如下。
<peoples>
<people id="1">
<name>李四</name>
<password>123456</password>
</people>
<people id="2">
<name>张三</name>
<password>174896</password>
</people>
<people id="3">
<name>王五</name>
<password>123</password>
</people>
</peoples>
第二步:
新建一个pojo,用来存储xml中解析的数据:
public class People {
private int id;
private String name;
private String password;
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 String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "People [id=" + id + ", name=" + name + ", password=" + password + "]";
}
}
第三步:
新建一个XML解析处理器类,该类是XML解析的核心,需要继承DefaultHandler,并且需要重写五个方法。他们分别是:
/**
* 文档开始时调用,只调用一次
*/
@Override
public void startDocument() throws SAXException{
super.startDocument();
}
/**
* 文档结束时调用
*/
@Override
public void endDocument() throws SAXException{
super.endDocument();
}
/**
* 结点开始时调用
* 主要用到的参数为qName和attributes。
* qName为当前结点的名称
* attributes为当前结点的属性值,根据索引可以取到(attributes.getValue(i))
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
}
/**
* 结点结束时调用
* 一般 做结点结束时的收尾工作
*/
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException{
}
/**
* 该方法解析当前标签的内容,如<name>李四</name>,则获取“李四”
*/
@Override
public void characters(char[] ch, int start, int length)
throws SAXException{
}
XMLParserHandler完整代码:
public class XMLParserHandler extends DefaultHandler{
//最终的people列表
private List<People> peopleList;
//记录当前的people
private People people;
//记录当前结点名
private String tagName;
public List<People> getPeopleList() {
return peopleList;
}
public void setPeopleList(List<People> peopleList) {
this.peopleList= peopleList;
}
public void setPeople(People people) {
this.people = people;
}
public String getCurrentTag() {
return tagName;
}
public void setTagName(String tagName) {
this.tagName = tagName;
}
@Override
public void startDocument() throws SAXException{
userList = new ArrayList<>();
}
@Override
public void endDocument() throws SAXException{
super.endDocument();
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if(qName.equals("people")) {
people = new People();
people.setId(Integer.parseInt(attributes.getValue(0)));
}
//将当前结点名记录,供characters()方法和endElement()方法判断当前是哪个结点
this.tagName = qName;
}
/**
*
*/
@Override
public void characters(char[] ch, int start, int length)
throws SAXException{
//截取标签内字段值
String value = new String(ch,start,length);
if(this.tagName == null) {
return;
}
switch(this.tagName) {
case "name":
this.people.setName(value);
break;
case "password":
this.people.setPassword(value);
break;
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException{
if(qName.equals("people")) {
this.userList.add(this.people);
}
//因为tagName要多次使用,当前结点结束后,要将tagName置空
this.tagName = null;
}
}
其实一开始学SAX解析的时候有很多困惑,比如它的解析流程是怎样的。SAX解析是流解析,从头到尾扫描完,也就解析完了。所以除了startDocument()和endDocument()只会调用一次,其他的方法都会调用多次。
第四步:
新建一个工具类,用于获取解析后XMLParserHandler。
public static XMLParserHandler getXMLParserHandler() {
try {
// 构建SAXParser
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
// 实例化DefaultHandler对象
XMLParserHandler xmlParserHandler = new XMLParserHandler();
// 加载资源文件 转化为一个输入流
InputStream inputStream = xmlParserHandler.getClass().
getClassLoader().getResourceAsStream("people.xml");
// 调用parse()方法
parser.parse(inputStream, xmlParserHandler);
//返回解析后的XMLParserHandler
return xmlParserHandler;
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
}
return null;
}
编写测试类:
public static void main(String[] args) {
XmlParseUtil xmlParseUtil = new XmlParseUtil();
XMLParserHandler handler = xmlParseUtil.getXMLParserHandler();
List<People> peopleList = handler.getUserList();
for (People people : peopleList) {
System.out.println(people);
}
}
结果:
People [id=1, name=李四, password=123456]
People [id=2, name=张三, password=174896]
People [id=3, name=王五, password=123]
最后再记录一下Web项目中,通用的获取XMLParserHandler的工具类:
public static <T extends DefaultHandler> T getXmlResolveHelper(T handler, String path, ServletContext
servletContext) {
try {
// 构建SAXParser
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
// 加载资源文件 转化为一个输入流
InputStream stream = servletContext.getResourceAsStream(path);
// 调用parse()方法
parser.parse(stream, handler);
stream.close();
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
}
return handler;
}