加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

解析XML——DOM、Pull、SAX

发布时间:2020-12-15 22:54:31 所属栏目:百科 来源:网络整理
导读:读取XML主要有2种方法:DOM与SAX(Simple API for XML),在这里对这2种方法分别加以说明。 DOM(文档对象模型),为XML文档的解析定义了一组接口,解析器读入整个文档,然后构造一个驻留内存的树结构,然后代码就可以使用DOM接口来 操组整个树结构,其他点如下


读取XML主要有2种方法:DOM与SAX(Simple API for XML),在这里对这2种方法分别加以说明。

DOM(文档对象模型),为XML文档的解析定义了一组接口,解析器读入整个文档,然后构造一个驻留内存的树结构,然后代码就可以使用DOM接口来 操组整个树结构,其他点如下:

  • 优点:整个文档树都在内存当中,便于操作;支持删除、修改、重新排列等多功能。
  • 缺点:将整个文档调入内存(经常包含大量无用的节点),浪费时间和空间。
  • 使用场合:一旦解析了文档还需要多次访问这些数据,而且资源比较充足(如内存、CPU等)。

为了解决DOM解析XML引起的这些问题,出现了SAX。SAX解析XML文档为事件驱动。当解析器发现元素开始、元素结束,文本、文档的开始或者结束时,发送 事件,在程序中编写响应这些事件的代码,其特点如下:

  • 优点:不用事先调入整个文档,占用资源少。尤其在嵌入式环境中,极力推荐采用SAX进行解析XML文档。
  • 缺点:不像DOM一样将文档长期驻留在内存,数据不是持久的,事件过后,如没有保存数据,那么数据就会丢失。
  • 使用场合:机器性能有限,尤其是在嵌入式环境,如Android,极力推荐采用SAX进行解析XML文档。

大多数时间,使用 SAX 是比较安全的,并且 Android 提供了一种传统的 SAX 使用方法,以及一个便捷的 SAX 包装器。如果XML文档比较小,那么 DOM 可能是一种比较简单的方法。如果XML文档比较大,但只需要文档的一部分,则 XML Pull 解析器可能是更为有效的方法。最后对于编写 XML,Pull 解析器包也提供了一种便捷的方法。因此,无论我们的 XML 需求如何,Android 都能在一定程度上满足我们的需求。

下面我们详细介绍采用DOM的方法,读取XML文档的思路,这基本上与XML的结构是完全一样的。

首先加载XML文档(Document),

然后获 取文档的根结点(Element),

然后获取根结点中所有子节点的列表(NodeList),

然后使用再获取子节点列表中的需要读取的结点。

采用DOM读取XML文件,需要加载整个XML文件,在XML文件比较大的情况下,会导致Android设备内存紧张,为了避免这个问题,也可以采 用SAX的方法读取XML文件,不过SAX对结点的排序、增加结点等方面的操作相比DOM就有些复杂了。根据XML文件大小、数据处理的需求,选择合适的 读取的方法。


XML代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<person>
	<student id="2">
		<name>张三</name>
		<age>23</age>
	</student>
	<student id="5">
		<name>李四</name>
		<age>25</age>
	</student>
</person>

DOM解析:

java类代码:

package com.utils.parsexml;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * 使用DOM解析XML
 * 
 * @author 伟
 * 
 */
public class DomXMLTools {
	public static List<Student> parseXML(InputStream is) throws Exception {
		List<Student> stus = new ArrayList<Student>();
		Student stu = null;
		// 创建一个document解析工厂
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		Document doc = db.parse(is);
		Element element = doc.getDocumentElement();
		NodeList stuNodes = element.getElementsByTagName("student");
		for (int i = 0; i < stuNodes.getLength(); i++) {
			Element stuNode = (Element) stuNodes.item(i);
			stu = new Student();
			int id = Integer.parseInt(stuNode.getAttribute("id"));
			stu.setId(id);
			NodeList stuChilds = stuNode.getChildNodes();
			for (int j = 0; j < stuChilds.getLength(); j++) {
				Node childs = stuChilds.item(j);
				// 得到节点可能为回车或空格,所以必须判断
				if (childs.getNodeType() == Node.ELEMENT_NODE) {
					if (childs.getNodeName().equals("name")) {
						String name = childs.getFirstChild().getNodeValue();
						stu.setName(name);
					} else if (childs.getNodeName().equals("age")) {
						String ageStr = childs.getFirstChild().getNodeValue();
						int age = Integer.parseInt(ageStr);
						stu.setAge(age);
					}
				}
			}
			stus.add(stu);
		}
		return stus;
	}
}

Pull解析:

java类代码

package com.utils.parsexml;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

/**
 * 使用pull解析XML
 * 
 * @author 伟
 * 
 */
public class PullXMLTools {
	public static List<Student> parseXML(InputStream is,String encode)
			throws Exception {
		List<Student> list = null;
		Student stu = null;
		// 新建一个XMLpull解析工厂
		XmlPullParserFactory xf = XmlPullParserFactory.newInstance();
		// 获得XML解析类的引用
		XmlPullParser xp = xf.newPullParser();
		xp.setInput(is,encode);
		// 获得事件的类型
		int type = xp.getEventType();
		while (type != XmlPullParser.END_DOCUMENT) {
			switch (type) {
			case XmlPullParser.START_DOCUMENT:
				// XML文档开始
				list = new ArrayList<Student>();
				break;
			case XmlPullParser.START_TAG:
				// 解析一个开始标签,获取标签文本
				String tagName = xp.getName();
				if (tagName.equals("student")) {
					stu = new Student();
					// 获得属性值
					int id = Integer.parseInt(xp.getAttributeValue(0));
					stu.setId(id);
				} else if (tagName.equals("name")) {
					// 获取节点内容
					String name = xp.nextText();
					stu.setName(name);
				} else if (tagName.equals("age")) {
					int age = Integer.parseInt(xp.nextText());
					stu.setAge(age);
				}
				break;
			case XmlPullParser.END_TAG:
				// 解析一个结束标签,并清空当前学生对象
				if (xp.getName().equals("student")) {
					list.add(stu);
					stu = null;
				}
				break;
			}
			// 重新获取事件类型
			type = xp.next();
		}
		return list;
	}
}


SAX解析:

handler类:

package com.utils.parsexml;

import java.util.ArrayList;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * 解析XML处理器
 * 
 * @author 伟
 * 
 */
public class SaxHandler extends DefaultHandler {
	private List<Student> stus;
	private Student stu;
	private String currentTag;
	private String currentValue;

	public List<Student> getStus() {
		return stus;
	}

	@Override
	public void startDocument() throws SAXException {
		// 开始解析XML
		stus = new ArrayList<Student>();
	}

	@Override
	public void startElement(String uri,String localName,String qName,Attributes attributes) throws SAXException {
		// 开始读取标签,qName为标签文本
		currentTag = qName;
		if (currentTag.equals("student")) {
			stu = new Student();
			if (attributes != null) {
				String idStr = attributes.getValue(0);
				int id = Integer.parseInt(idStr);
				stu.setId(id);
			}
		}
	}

	@Override
	public void characters(char[] ch,int start,int length)
			throws SAXException {
		// 根据currentTag获取每个标签的内容
		if (currentTag != null) {
			currentValue = new String(ch,start,length);
			// 确保value不是回车或者空字符
			if (currentValue != null && !currentValue.trim().equals("")
					&& !currentValue.trim().equals("n")) {
				if (currentTag.equals("name")) {
					stu.setName(currentValue);
				} else if (currentTag.equals("age")) {
					stu.setAge(Integer.parseInt(currentValue));
				}
			}
		}
		// 把当前节点对应的值清空
		currentTag = null;
		currentValue = null;
	}

	@Override
	public void endElement(String uri,String qName)
			throws SAXException {
		// 遇到结束标签时调用
		currentTag = qName;
		if (currentTag.equals("student")) {
			stus.add(stu);
			stu = null;
		}
	}
}

java解析类:

package com.utils.parsexml;

import java.io.InputStream;
import java.util.List;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class SaxXMLTools {
	public static List<Student> parseXML(InputStream is) throws Exception {
		List<Student> stus = null;
		// 创建一个XML解析处理器
		SaxHandler sh = new SaxHandler();
		// 创建一个SAX解析工厂
		SAXParserFactory spf = SAXParserFactory.newInstance();
		// 创建SAX解析器
		SAXParser sp = spf.newSAXParser();
		// 解析xml,将每个事件发给处理器
		sp.parse(is,sh);
		is.close();
		return sh.getStus();
	}
}

实体类:

package com.utils.parsexml;

public class Student {
	private int id;
	private String name;
	private int age;

	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;
	}

	public Student(int id,String name,int age) {
		this.id = id;
		this.name = name;
		this.age = age;
	}

	public Student() {
	}

	@Override
	public String toString() {
		return "Studnet [id=" + id + ",name=" + name + ",age=" + age + "]";
	}
}


测试类:
package com.utils.parsexml;

import java.io.InputStream;
import java.util.List;

public class Test {

	/**
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		InputStream is = Test.class.getClassLoader().getResourceAsStream(
				"person.xml");
		// List<Student> stus = PullXMLTools.parseXML(is,"utf-8");
		// List<Student> stus = DomXMLTools.parseXML(is);
		List<Student> stus = SaxXMLTools.parseXML(is);
		for (Student student : stus) {
			System.out.println(student.toString());
		}
	}

}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读