`
左手边
  • 浏览: 94474 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

xml常用四种解析方式优缺点的分析

    博客分类:
  • xml
 
阅读更多

      最近用得到xml的解析方式,于是就翻了翻自己的笔记同时从网上查找了资料,自己在前人的基础上总结了下,贴出来大家分享下。

首先介绍一下xml语言:

可扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。

xml的语法:

XML 分为两部分:头信息,主体信息

头信息是用来描述 XML 的一些属性,例如:版本,编码等,还可以提供 XML 显示的样式,和 dtd 编写格式。

主体信息中包含的是 XML 的具体数据。

 

头信息的语法:

<?xml version =”1.0” encoding =”GBK” ?>

其中 version 是必须加的,而 encoding 可以不写,则默认编码是 ISO8859-1 ,不支持中文。

除了这个功能外,头信息还可以进行编写格式的规定,通过 dtd xsd 文件。

头信息还支持样式表的导入,允许通过样式表控制 XML 的显示。

这样可以使用 XML+ CSS 完成页面的显示,通过这种形式完成 MVC 中的 View 层:

优点:代码的安全性很高,可以很容易的替换模板。

缺点:开发成本太高

主体信息 就是由三种节点组成的,节点之间存在父与子的关系,注意的点:

  一个节点只能有一个父节点,如果没有父节点,该节点称为根节点。

  一个节点可以有多个子节点。只有元素节点可以拥有子节点。

  元素节点的标记必须成对出现,或直接结束。

特殊字符必须转义。依据字符所处的位置是否对 XML 格式造成影响来决定是否进行转义

根节点只能有一个

xml常用的四种解析方式:

1)DOM(Document Object Model)

文档对象模型分析方式。以层次结构(类似于树型)来组织节点和信息片段,映射XML文档的结构,允许获取和操作文档的任意部分。是W3C的官方标准。

优点:
1、允许应用程序对数据和结构做出更改。
2、访问是双向的,可以在任何时候在树中上下导航,获取和操作任意部分的数据。

缺点:
1、通常需要加载整个XML文档来构造层次结构,消耗资源大

2)SAX(Simple API for XML)

流模型中的推模型分析方式。通过事件驱动,每发现一个节点就引发一个事件,通过回调方法完成解析工作,解析XML文档的逻辑需要应用程序完成。

优点:
1、不需要等待所有数据都被处理,分析就能立即开始。
2、只在读取数据时检查数据,不需要保存在内存中。
3、可以在某个条件得到满足时停止解析,不必解析整个文档。
4、效率和性能较高,能解析大于系统内存的文档。

缺点:
1、需要应用程序自己负责TAG的处理逻辑(例如维护父/子关系等),使用麻烦。
2、单向导航,很难同时访问同一文档的不同部分数据,不支持XPath。

3)JDOM(Java-based Document Object Model)

Java特定的文档对象模型。自身不包含解析器,使用SAX。

优点:
1、使用具体类而不是接口,简化了DOM的API。
2、大量使用了Java集合类,方便了Java开发人员。

缺点:
1、没有较好的灵活性。
2、性能较差。

4)DOM4J(Document Object Model for Java)

简单易用,采用Java集合框架,并完全支持DOM、SAX和JAXP。

优点:
1、大量使用了Java集合类,方便Java开发人员,同时提供一些提高性能的替代方法。
2、支持XPath。
3、有很好的性能。

缺点:
1、大量使用了接口,API较为复杂。

下面把四种解析方式的代码贴一下,首先是DOM方式

public class DOMXml {
	
	public static void createXML(String outputPath) {
		// 建立Document对象
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		// 创建DocumentBuilder
		try {
			DocumentBuilder db = factory.newDocumentBuilder();
			// 创建Document,建立新的对象
			Document doc = db.newDocument();

			// 建立各个节点
			// 元素节点
			Element allplus = doc.createElement("allplus");
			
			Element areaplus = doc.createElement("areaplus");
			Element id = doc.createElement("id");
			Element title = doc.createElement("title");
			// 创建文本节点
			Text idText = doc.createTextNode("1");
			Text titleText = doc.createTextNode("123");

			// 配置父子节点的关系
			id.appendChild(idText);
			title.appendChild(titleText);

			areaplus.appendChild(id);
			areaplus.appendChild(title);

			allplus.appendChild(areaplus);


			// allplus是根节点,应该设置为doc的子节点
			doc.appendChild(allplus);

			// 执行保存操作
			TransformerFactory tf = TransformerFactory.newInstance();

			Transformer t = tf.newTransformer();

			// 包装要保存的doc
			DOMSource source = new DOMSource(doc);
			// 设置输出流
			StreamResult sr = new StreamResult(new File(outputPath));

			// 设置输出的属性
			t.setOutputProperty("encoding", "UTF-8");
			// t.setOutputProperty("version", "1.0");

			// 输出
			t.transform(source, sr);

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

	}


	public static void parseXML(String xmlPath) {
		
		/*优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能;
		 * 缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间;
		 * 使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)。 
		 * 10M文档导致内存溢出	
		 */
		
		// 建立Document对象
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		// 创建DocumentBuilder
		try {
			DocumentBuilder db = factory.newDocumentBuilder();
			// 创建Document,形成树型结构
			Document doc = db.parse(new File(xmlPath));
			// 先取得所有的data
			NodeList datas = doc.getElementsByTagName("data");
			// 循环取得每个data
			for (int i = 0; i < datas.getLength(); i++) {
				Node data = datas.item(i);
				// 由于直接取得第一个和最后一个不符合要求,因此使用取得全部子节点的方式
				NodeList actorInfos = data.getChildNodes();
				for (int j = 0; j < actorInfos.getLength(); j++) {
					Node actorInfo = actorInfos.item(j);
					NodeList allChild = actorInfo.getChildNodes();
					for (int t = 0; t < allChild.getLength(); t++) {
						//判断节点
						Node child = allChild.item(t);
						if (child.getNodeType() == Node.ELEMENT_NODE) {
							if (child.getNodeName().equals("id")) {
								//判断是否有孩子节点,然后再取值
								if(child.hasChildNodes()) {
									System.out.println(child.getFirstChild().getNodeValue());
								}
							}
							if (child.getNodeName().equals("name")) {
								//判断是否有孩子节点,然后再取值
								if(child.hasChildNodes()) {
									System.out.println(child.getFirstChild().getNodeValue());
								}
							}
						}
					}
				}
			}
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public static void main(String[] args) {
		parseXML("D:/actor_info.xml");
		createXML("d:/fxb.xml");
	}

 SAX解析方式

public class SAXXml 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();
		SAXXml handler = new SAXXml();
		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));
			}
		}
	}

	public static void main(String args[]) {
		
		SAXXml handler = new SAXXml();

		// 定义SUN自带解析对象
		SAXParser parser;
		try {
			parser = SAXParserFactory.newInstance().newSAXParser();
			parser.parse(new File("D:/book.xml"), handler);
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		List<Book> books = handler.getBooks();
		for (Book book : books) {
			System.out.println(book.toString());
		}
	}

 JDOM解析方式

public class JDOMXml {
	
	public static void createXML(String outputPath) {
		// 先建立Document对象
		Document doc = new Document();
		// 建立元素节点
		Element allplus = new Element("allplus");

		try {
			// 建立多个Element
			Element areaplus = new Element("areaplus");
			Element id = new Element("id");
			Element title = new Element("title");
			// 设置节点内容
			id.addContent("id");
			title.addContent("title");
			// 设置父子节点关系
			areaplus.addContent(id);
			areaplus.addContent(title);
			allplus.addContent(areaplus);
			// 设置根节点
			doc.setRootElement(allplus);

			// 使用IO流操作
			FileWriter writer = new FileWriter(new File(outputPath));

			// 定义输出对象
			XMLOutputter outputter = new XMLOutputter();
			// 设置编码
			outputter.setEncoding("UTF-8");
			// 输出
			outputter.output(doc, writer);
			writer.close();

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

	}

	public static void parseXML(String xmlPath) {
		/*
		 * 10M文档导致内存溢出
		 */
		//完成解析功能。
		SAXBuilder builder = new SAXBuilder();
		try {
			Document doc = builder.build(new File(xmlPath));
			// 开始解析,取得根节点
			Element data = doc.getRootElement();
			// 取得所有的areaplus
			List<Element> actorInfos = data.getChildren("actor_info");
			if(actorInfos != null && actorInfos.size()>0) {
				for(Element actorInfo:actorInfos) {
					Element id = actorInfo.getChild("id");
					Element name = actorInfo.getChild("name");
					System.out.println(id.getTextTrim() + " --- " + name.getTextTrim());
				}
			}
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		parseXML("D:/actor_info.xml");
		createXML("d:/fdfdsf.xml");
	}

 DOM4J解析方式

package com.fxb.test;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Iterator;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

/**
 * 
 * @author hongliang.dinghl Dom4j 生成XML文档与解析XML文档
 */
public class DOM4JXml {

	public void createXml(String fileName) {
		Document document = DocumentHelper.createDocument();
		Element employees = document.addElement("data");
		Element employee = employees.addElement("actor_info");
		Element id = employee.addElement("id");
		id.setText("1");
		Element name = employee.addElement("name");
		name.setText("你好");
		Element message = employee.addElement("message");
		message.setText("你好吗");
		Element pic = employee.addElement("pic");
		pic.setText("123");
		Element sex = employee.addElement("sex");
		pic.setText("男");
		Element birthday = employee.addElement("birthday");
		pic.setText("19881212");
		try {
			Writer fileWriter = new FileWriter(fileName);
			XMLWriter xmlWriter = new XMLWriter(fileWriter);
			xmlWriter.write(document);
			xmlWriter.close();
		} catch (IOException e) {
			System.out.println(e.getMessage());
		}

	}

	public void parserXml(String fileName) {
		File inputXml = new File(fileName);
		SAXReader saxReader = new SAXReader();
		try {
			Document document = saxReader.read(inputXml);
			Element data = document.getRootElement();
			for (Iterator i = data.elementIterator(); i.hasNext();) {
				Element actorInfo = (Element) i.next();
				//System.out.println(employee.getName() + "->" + employee.getText());
				for (Iterator j = actorInfo.elementIterator(); j.hasNext();) {
					Element child = (Element) j.next();
					System.out.println(child.getName() + ":" + child.getText());
				}
				System.out.println("=================");
			}
		} catch (DocumentException e) {
			System.out.println(e.getMessage());
		}
	}
	
	public static void main(String args[]) {
		DOM4JXml dom = new DOM4JXml();
		//dom.parserXml("d:/actor_info.xml");
		dom.createXml("d:/fxb.xml");
	}
}
 

 

 

4
2
分享到:
评论
1 楼 hecal 2012-08-11  
god,兄弟你的代码有个bug.
在你的SAX解析方式里,有一个小bug.其他的没看。

50.    @Override 
51.    public void characters(char[] ch, int start, int length) 
52.            throws SAXException { 
53.        if (preTag != null) { 
54.            String content = new String(ch, start, length); 
55.            if ("name".equals(preTag)) { 
56.                book.setName(book.getName() + content); 
57.            } else if ("price".equals(preTag)) { 
58.                book.setPrice(Float.parseFloat(content)); 
59.            } 
60.        } 
61.    } 

原因:当name是很长的文章的时候,就被切断了,结果出错了。

相关推荐

    Android编程创建与解析xml的常用方法详解

    其次是解析xml文件,常用的有dom,sax,XmlPullParser等方法,由于sax代码有点复杂,本节只讲解一下dom与XmlPullParser解析,sax我将会在下一节单独讲解,至于几种解析xml的优缺点我就不再讲述了。 为了方便理解,我做...

    DWR.xml配置文件说明书(含源码)

    一种情况是因为解析器是一个语法宽松的解析器,他不象编译器一样对语法有非常严格的要求,所有有时可能一些重要的语句没有配置而无法事先发现. &lt;![CDATA[ import java.util.List; Check.setLotteryResults...

    Java面试宝典2010版

    解析XML文档有哪几种方式? 七. 流行的框架与新技术 1、谈谈你对Struts的理解。 2、谈谈你对Hibernate的理解。 3、AOP的作用。 4、你对Spring的理解。 5、谈谈Struts中的Action servlet。 6、Struts优缺点 ...

    最新Java面试宝典pdf版

    解析XML文档有哪几种方式? 117 七. 流行的框架与新技术 117 1、谈谈你对Struts的理解。 117 2、谈谈你对Hibernate的理解。 118 3、AOP的作用。 118 4、你对Spring的理解。 118 5、谈谈Struts中的Action servlet。 ...

    Java面试笔试资料大全

    解析XML文档有哪几种方式? 117 七. 流行的框架与新技术 117 1、谈谈你对Struts的理解。 117 2、谈谈你对Hibernate的理解。 118 3、AOP的作用。 118 4、你对Spring的理解。 118 5、谈谈Struts中的Action servlet。 ...

    JAVA面试宝典2010

    解析XML文档有哪几种方式? 117 七. 流行的框架与新技术 117 1、谈谈你对Struts的理解。 117 2、谈谈你对Hibernate的理解。 118 3、AOP的作用。 118 4、你对Spring的理解。 118 5、谈谈Struts中的Action servlet。 ...

    Java面试宝典-经典

    解析XML文档有哪几种方式? 117 七. 流行的框架与新技术 117 1、谈谈你对Struts的理解。 117 2、谈谈你对Hibernate的理解。 118 3、AOP的作用。 118 4、你对Spring的理解。 118 5、谈谈Struts中的Action servlet。 ...

    java面试题大全(2012版)

    解析XML文档有哪几种方式? 117 七. 流行的框架与新技术 117 1、谈谈你对Struts的理解。 117 2、谈谈你对Hibernate的理解。 118 3、AOP的作用。 118 4、你对Spring的理解。 118 5、谈谈Struts中的Action servlet。 ...

    Java面试宝典2012版

    解析XML文档有哪几种方式? 117 七. 流行的框架与新技术 117 1、谈谈你对Struts的理解。 117 2、谈谈你对Hibernate的理解。 118 3、AOP的作用。 118 4、你对Spring的理解。 118 5、谈谈Struts中的Action ...

    java面试宝典2012

    解析XML文档有哪几种方式? 127 七. 流行的框架与新技术 128 1、谈谈你对Struts的理解。 128 2、谈谈你对Hibernate的理解。 128 3、AOP的作用。 129 4、你对Spring的理解。 129 5、谈谈Struts中的Action servlet。 ...

    Java面试宝典2012新版

    解析XML文档有哪几种方式? 117 七. 流行的框架与新技术 117 1、谈谈你对Struts的理解。 117 2、谈谈你对Hibernate的理解。 118 3、AOP的作用。 118 4、你对Spring的理解。 118 5、谈谈Struts中的Action servlet。 ...

    springboot学习思维笔记.xmind

    SpringBoot的优缺点 优点 快速构建项目 对主流开发框架的无配置集成 项目可独立运行,无需外部依赖Servlet容器 提供运行时的应用监控 极大地提高了开发,部署效率 与云计算的...

    EMET快捷键

    HBuilder的一些常用快捷键 Emmet (前身为 Zen Coding) 是一个能大幅度提高前端开发效率的一个工具: 基本上,大多数的文本编辑器都会允许你存储和重用一些代码块,我们称之为“片段”。虽然片段能很好地推动你得...

    asp.net知识库

    Asp.Net(C#)利用XPath解析XML文档示例 XSL .Net框架下的XSLT转换技术简介 一个XSLT的简单例子 XSLXSLT板主题整理 xsl入门的好文章 新手学习XSL的好东西 XSL语法介绍 XSL学习心得 - 调用属性值 XSLT与XML转换的详细...

    phpMyAdmin v4.8.5.zip

    您可以设置cookie,管理数字签名和重定向用户,而且它提供了极好的连通性到其它数据库(还有ODBC),集成各种外部库来做用PDF文档解析XML的任何事情.[1] phpMyAdmin 是一个用PHP编写的软件工具,可以通过web方式控制和...

    千方百计笔试题大全

    203、编程用JAVA解析XML的方式. 49 204、EJB2.0有哪些内容?分别用在什么场合? EJB2.0和EJB1.1的区别? 51 205、EJB与JAVA BEAN的区别? 51 206、EJB的基本架构 51 207、MVC的各个部分都有那些技术来实现?如何实现? 52...

    java面试宝典

    203、编程用JAVA解析XML的方式. 49 204、EJB2.0有哪些内容?分别用在什么场合? EJB2.0和EJB1.1的区别? 51 205、EJB与JAVA BEAN的区别? 51 206、EJB的基本架构 51 207、MVC的各个部分都有那些技术来实现?如何实现? 52...

Global site tag (gtag.js) - Google Analytics