Java--xml文件的解析

本文对比了DOM和SAX两种XML解析方式的特点与应用场景。DOM解析方式将整个XML文档加载到内存中,便于操作但消耗资源较多;SAX解析方式采用事件驱动,逐行读取文档,适用于大文件解析但编程复杂度较高。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要讲述两个xml的解析方式:DOM解析和SAX解析。

一、DOM解析步骤:

1.通过文档解析器的工厂对象DocumentBuilderFactory得到一个文档解析DocunmentBuilder对象builder

2.通过输入流对象is获取xml文件内容

3.通过解析器的parse方法解析输入流对象is,并转换成Document对象document

4.获取文档的根节点document.getDocumentElement();

5.判断是否有孩子节点

6.获取所有的子节点对象,并判断每个子节点对象的类型,以获取指定类型节点的数据

7.将获取节点中的值并赋给实体化对象

示例代码如下:

package www.youkuaiyun.com.activityg.xml;

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.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import www.youkuaiyun.com.activityg.domain.City;

public class DOMXML {

	public List<City> domXml() {
		// 创建返回的集合对象
		List<City> cities = new ArrayList<City>();
		// 创建问文档解析器的工厂对象
		DocumentBuilderFactory builderFactory = DocumentBuilderFactory
				.newInstance();
		try {
			// 得到文档解析器对象
			DocumentBuilder builder = builderFactory.newDocumentBuilder();
			// 获取输入流对象
			InputStream is = getClass().getClassLoader().getResourceAsStream(
					"china.xml");
			// 通过解析器的parse方法 解析is对象,转换成 Document对象
			Document document = builder.parse(is);
			// 返回的是文档的跟节点
			Element rootElement = document.getDocumentElement();
			// 判断是否有孩子节点
			if (rootElement.hasChildNodes()) {
				// 获取所有的子节点
				NodeList nodeList = rootElement.getChildNodes();
				// 遍历子节点
				for (int i = 0; i < nodeList.getLength(); i++) {
					// 获取子节点对象
					Node node = nodeList.item(i);

					// 元素节点的类型值:1 文本类型的类型节点值:3 属性节点的类型值:2
					// 判断这个子节点是什么类型的子节点 文本节点 元素节点
					if (node.getNodeType() == Element.ELEMENT_NODE) {
						// 创建一个实体对象 保存元素节点值
						City city = new City();
						// 造型
						Element element = (Element) node;
						// 得到这个节点中的所有属性节点
						NamedNodeMap map = element.getAttributes();
						//-------------- 遍历属性节点开始-----------------------
						for (int j = 0; j < map.getLength(); j++) {
							// 获取具体的某个属性节点
							Attr attr = (Attr) map.item(j);
							// 具体判断
							if ("cityname".equals(attr.getNodeName())) {
								// 设置对象的属性值
								city.setCityName(attr.getNodeValue());
							} else if ("pyName".equals(attr.getNodeName())) {
								city.setPyName(attr.getNodeValue());
							} else if ("quName".equals(attr.getNodeName())) {
								city.setQuName(attr.getNodeValue());
							} else if ("state1".equals(attr.getNodeName())) {
								city.setState1(attr.getNodeValue());
							} else if ("state2".equals(attr.getNodeName())) {
								city.setState2(attr.getNodeValue());
							} else if ("stateDetailed".equals(attr
									.getNodeName())) {
								city.setStateDetailed(attr.getNodeValue());
							} else if ("tem1".equals(attr.getNodeName())) {
								city.setTem1(attr.getNodeValue());
							} else if ("tem2".equals(attr.getNodeName())) {
								city.setTem2(attr.getNodeValue());
							} else if ("windState".equals(attr.getNodeName())) {
								city.setWindState(attr.getNodeValue());
							}

						}
						//-------------------遍历属性节点的结束-------------------------------
						// 添加到集合中
						cities.add(city);

					}
				}

			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return cities;

	}
}

DOM的优势主要表现在:易用性强,使用DOM时,将把所有的XML文档信息都存于内存中,并且遍历简单,支持XPath,增强了易用性。

DOM的缺点主要表现在:效率低,解析速度慢,内存占用量过高,对于大文件来说几乎不可能使用。另外效率低还表现在大量的消耗时间,因为使用DOM进行解析时,将为文档的每个elementattributeprocessing-instrUCtioncomment都创建一个对象,这样在DOM机制中所运用的大量对象的创建和销毁无疑会影响其效率。

所以DOM解析适用于小型xml文档的解析。






二、SAX

SAX不像DOM那样建立一个完整的文档树,而是在读取文档时激活一系列事件,这些事件被推给事件处理器,然后由事件处理器提供对文档内容的访问。通过继承DefaultHandler,并重写其中的方法来实现对xml文档的解析。

SAX的优点在于内存消耗少,可以解析大文件。缺点在于Sax解析是按照xml文件的顺序一步一步的来解析,如果xml文档结构非常的复杂,则会给编程带来麻烦。

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

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

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

import com.xtlh.cn.entity.Book;

public class SaxParseService extends DefaultHandler{
	private List<Book> books = null;
	private Book book = null;
	private String preTag = null;//作用是记录解析时的上一个节点名称
	
	public List<Book> getBooks(InputStream xmlStream) throws Exception{
		SAXParserFactory factory = SAXParserFactory.newInstance();
		SAXParser parser = factory.newSAXParser();
		SaxParseService handler = new SaxParseService();
		parser.parse(xmlStream, handler);
		return handler.getBooks();
	}
	
	public List<Book> getBooks(){
		return books;
	}
	
	@Override
	public void startDocument() throws SAXException {
		books = new ArrayList<Book>();
	}

	@Override
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
		if("book".equals(qName)){
			book = new Book();
			book.setId(Integer.parseInt(attributes.getValue(0)));
		}
		preTag = qName;//将正在解析的节点名称赋给preTag
	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		if("book".equals(qName)){
			books.add(book);
			book = null;
		}
		preTag = null;/**当解析结束时置为空。这里很重要,例如,当图中画3的位置结束后,会调用这个方法
		,如果这里不把preTag置为null,根据startElement(....)方法,preTag的值还是book,当文档顺序读到图
		中标记4的位置时,会执行characters(char[] ch, int start, int length)这个方法,而characters(....)方
		法判断preTag!=null,会执行if判断的代码,这样就会把空值赋值给book,这不是我们想要的。*/
	}
	
	@Override
	public void characters(char[] ch, int start, int length) throws SAXException {
		if(preTag!=null){
			String content = new String(ch,start,length);
			if("name".equals(preTag)){
				book.setName(content);
			}else if("price".equals(preTag)){
				book.setPrice(Float.parseFloat(content));
			}
		}
	}
	
}
代码来自http://www.iteye.com/topic/763895

三、DOM与SAX的区别

1.DOM把所有的XML文档信息都存于内存中

2.Sax无需一次把xml文件加载到内存中,采用的事件驱动的操作

3.应用场景不一样,dom适合复杂结构小型xml文档,sax适用于简单结构大型xml。

4.dom可以直接获取某个节点,Sax只能按步骤读取。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值