[置顶] Android开发之XML文件的解析

时间:2023-03-08 17:50:45

Android系统开发之XML文件的解析

我们知道Http在网络传输中的数据组织方式有三种分别为:XML方式、HTML方式、JSON方式。其中XML为可扩展标记语言,如下:

<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person id="23">
<name>Jack</name>
<age>23</age>
</person>
<person id="20">
<name>Tom</name>
<age>25</age>
</person>
</persons>

Android中解析XML数据有三种方式:分别为
DOM、SAX、和XMLPULL。下面我们分别介绍这三种方式:

1)SAX(org.xml.sax) 方式

Simple API for XML,以事件的形式通知程序,对XML进行解析。SAX是一种以事件驱动的XML api,由他定义的事件流可以指定从解析器传到专门的处理程序的代码的XML结构,特点是:解析速度快,占用内存少。

代码流程:
1) 定义一个类继承于DefaultHandler,重写其startDocument、startElement、endDocument、endElement、characters三个方法。

public class MySaxHandler extends DefaultHandler {

	private HashMap<String, String> map = null;	// 存储单个解析的完整对象
private List<HashMap<String, String>> list = null; // 存储所有的解析对象 private String currentTag = null; // 正在解析的元素的标签
private String currentValues = null; // 解析当前元素的值
private String nodeName = null; // 解析当前的节点名称 public MySaxHandler(String nodeName) {
// TODO Auto-generated constructor stub
this.nodeName = nodeName;
} /**
* @return the list
*/
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 endDocument() throws SAXException {
// TODO Auto-generated method stub
super.endDocument();
} @Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// 遇到结束标记的时候调用
if(qName.equals(nodeName)) {
list.add(map);
map = null;
}
} @Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// 处理XML文件所读取到的内容
if(currentTag != null && map != null) {
currentValues = new String(ch, start, length);
if(currentValues != null && !currentValues.trim().equals("") &&
!currentValues.trim().equals("\n")) {
map.put(currentTag, currentValues);
}
}
currentTag = null; // 当前节点对应的值和标签设置为空
currentValues = null;
}
}

2) 定义一个处理流的类SaxService,调用SAXParserFactory创建一个SAXParser从输入流解析XML文件。

public class SaxService {

	public static List<HashMap<String, String>> readXml(
InputStream inputStream, String nodeName) {
try {
// 创建一个解析XML的工厂对象
SAXParserFactory spFactory = SAXParserFactory.newInstance();
SAXParser parser = spFactory.newSAXParser();
MySaxHandler handler = new MySaxHandler(nodeName);
parser.parse(inputStream, handler);
inputStream.close();
return handler.getList(); } catch (Exception e) {
// TODO: handle exception
}
return null;
} public SaxService() {
}
}

3) 定义一个测试类Test,读取文件FileInputStream调用SaxService.readXml()处理。

public class Test {

	/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
File file = new File("C://test.xml");
if(file.exists()) {
FileInputStream inputStream = new FileInputStream(file);
List<HashMap<String, String>> list = SaxService.readXml(inputStream, "person");
for(HashMap<String, String> map : list) {
System.out.println(map.toString());
}
} else {
System.out.println("file is not exitst");
} } catch (Exception e) {
// TODO: handle exception
}
}
}

2)DOM方式

DOM是一种用于XML文档对象模型,可用于直接访问XML文档的各个部位,在DOM中文档被模拟为树桩
其中XML语法的每一个组成部分都表示一个节点,DOM允许用户遍历文档树,从父节点到子节点
和兄弟节点,并利用某节点类型特有的属性。

节点类型:
       整个文档是一个节点文档,每个xml标签是一个元素节点,包含在XML元素中的文本是文本节点每个XML属性是一个属性节点。

public class DomXml {

	public DomXml() {
// TODO Auto-generated constructor stub
} public List<Person> getPersons(InputStream inputStream) throws Exception {
List<Person> list = new ArrayList<Person>();
// 创建一个document解析的工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(inputStream);
Element element = document.getDocumentElement();
NodeList personNodeList = element.getElementsByTagName("person");
for(int i = 0; i < personNodeList.getLength(); i++) {
Element personElement = (Element)personNodeList.item(i);
Person person = new Person();
person.setId(Integer.parseInt(personElement.getAttribute("id")));
NodeList childNodes = personElement.getChildNodes();
for(int j = 0; j < childNodes.getLength(); j++) {
if(childNodes.item(j).getNodeType() == Node.ELEMENT_NODE) {
if("name".equals(childNodes.item(j).getNodeName())) {
person.setName(childNodes.item(j).getFirstChild().getNodeValue());
} else if("age".equals(childNodes.item(j).getNodeName())) {
person.setAge(Integer.parseInt(childNodes.item(j).getFirstChild().getNodeValue()));
}
}
}
list.add(person);
}
return list;
} public static void main(String[] args) throws Exception { FileInputStream inputStream = new FileInputStream("C://test.xml");
DomXml domXml = new DomXml();
List<Person> list = domXml.getPersons(inputStream);
for(Person person : list) {
System.out.println(person.toString());
}
}
}

3)XMLPULL(org.xmlpull.v1) 方式

1) 新建一个项目,导入kxml2-2.2.2.jar包,创建一个描述信息Person类。

        kxml2-2.2.2.jar包下载地址:http://download.****.net/detail/llping2010/6270791

public class Person {

	private String name;
private int age;
private int id; public Person() {
// TODO Auto-generated constructor stub
} public Person(String name, int age, int id) {
super();
this.name = name;
this.age = age;
this.id = id;
} /**
* @return the name
*/
public String getName() {
return name;
} /**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
} /**
* @return the age
*/
public int getAge() {
return age;
} /**
* @param age the age to set
*/
public void setAge(int age) {
this.age = age;
} /**
* @return the id
*/
public int getId() {
return id;
} /**
* @param id the id to set
*/
public void setId(int id) {
this.id = id;
} /* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", id=" + id + "]";
}
}

2) 创建一个PullXmlTools类,根据inputStream获取输入调用XmlPullParserFactoty解析XML将解析的数据保存到List<Person> list中返回。

public class PullXmlTools {

	public PullXmlTools() {
// TODO Auto-generated constructor stub
} public static List<Person> parseXml(InputStream inputStream, String encode) throws XmlPullParserException, IOException {
List<Person> list = null;
Person person = null; // 创建一个xml解析的工厂
XmlPullParserFactory xppFactovy = XmlPullParserFactory.newInstance();
// 获得xml解析类的引用
XmlPullParser parser = xppFactovy.newPullParser();
// 设置parser解析器的输入和编码类型
parser.setInput(inputStream, 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("person".equals(parser.getName())) {
person = new Person();
int id = Integer.parseInt(parser.getAttributeName(0));
person.setId(id);
} else if("name".equals(parser.getName())) {
String name = parser.nextText();
person.setName(name);
} else if ("age".equals(parser.getName())) {
int age = Integer.parseInt(parser.nextText());
person.setAge(age);
}
break; case XmlPullParser.END_TAG:
if("person".equals(parser.getName())) {
list.add(person);
person = null;
}
break;
}
eventType = parser.getEventType();
}
return list;
}
}

3) 定义一个测试类Test,读取文件FileInputStream调用PullXmlTools.parserXml()处理。

public class Test {

	/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub try {
File file = new File("C://test.xml");
if(file.exists()) {
FileInputStream inputStream = new FileInputStream(file);
List<Person> list = PullXmlTools.parseXml(inputStream, "utf-8");
for(Person person : list) {
System.out.println(person.toString());
}
} else {
System.out.println("file is not exitst");
} } catch (Exception e) {
// TODO: handle exception
}
}
}