无废话XML--XML解析(DOM和SAX)
- XML处理模式
处理XML有2种方式,DOM和SAX。一般的实际开发中,这2种使用的不多,直接用dom4j来解析XML就好了,包括CRUD等操作都很方便的。这里介绍的DOM和SAX是比较底层的,具体的API在jdk中可以查到的。
- 一、 DOM 文档对象模式
1.DOM特点:
以树型结构访问XML文档。 一棵DOM树包含全部元素节点和文本节点。可以前后遍历树中的每一个节点。
整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能。 将整个文档调入内存(包括无用的节点),浪费时间和空间。 一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)情况下使用。
2.DOM树与节点
XML文档被解析成树型结构。 树由节点组成。共有12种不同的节点。 节点可以包含其他节点(依赖于节点的类型)。 父节点包含子节点。叶子节点没有子节点。
3.节点类型
知道下面这3种比较常用的就好了:Document(节点) Element(元素) Attribute(属性)
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
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 org.xml.sax.SAXException; public class LinkinDOMParser
{ public static void main(String[] args) throws SAXException, IOException, ParserConfigurationException
{
//创建一个DOM解析器工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//从工厂中生成一个DOM解析器; throws ParserConfigurationException
DocumentBuilder builder = factory.newDocumentBuilder();
//绑定需要解析的XML文件
File xmlFile = new File("src/data-sources.xml");//相对地址,相对于这个工程
//开始解析 ;throws SAXException,IOException
Document document = builder.parse(xmlFile);
//取出唯一的根元素
Element rootElement = document.getDocumentElement();
//调用业务方法: 遍历根元素
printElement(rootElement);
} /** 遍历元素,包含: 子元素、属性、文本内容 */
private static void printElement(Element e)
{
//打印出元素的标签名
System.out.print("<" + e.getTagName());
//获取开始标签的属性
NamedNodeMap attMap = e.getAttributes();
//循环遍历所有的属性
for (int i = 0; i < attMap.getLength(); i++)
{
Attr attr = (Attr) attMap.item(i);
System.out.print(" " + attr.getName() + "=" + attr.getValue());
}
System.out.print(">"); //获取当前元素的所有子节点
NodeList nl = e.getChildNodes();
for (int j = 0; j < nl.getLength(); j++)
{
Node n = nl.item(j);
if (Node.ELEMENT_NODE == n.getNodeType())// getNodeType:表示基础对象的类型的节点,如上所述。
{
printElement((Element) n);//递归调用,以遍历下一个元素
}
else
{
System.out.print(n.getTextContent());
}
}
//打印结束标签
System.out.print("</" + e.getTagName() + ">");
} }
<?xml version="1.0" encoding="UTF-8"?>
<DataSource>
<database name="mysql" version="5.0">
<driver>com.mysql.jdbc.Driver</driver>
<url>jdbc:mysql://localhost:3306/linkinjdbc</url>
<user>root</user>
<password>root</password>
</database> <database name="Oracle" version="10G">
<driver>oracle.jdbc.driver.OracleDriver</driver>
<url>jdbc:oracle:thin:@127.0.0.1:linkinOracle</url>
<user>system</user>
<password>root</password>
</database>
</DataSource>
- 二、 SAX 基于事件处理模式
解析器向一个事件处理程序发送事件,比如元素开始和元素结束,而事件处理器则处理该信息。 然后应用程序本身就能够处理该数据。原始的文档仍然保留完好无损。
1. 为什么会出现 SAX 解析?
在使用 DOM 解析 XML 文档时,需要读取整个 XML 文档,在内存中构架代表整个DOM 树的 Doucment 对象,从而再对 XML 文档进行操作。此种情况下,如果 XML 文档特别大,就会消耗计算机的大量内存,并且容易导致内存溢出。SAX 解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作。注意:sax 只能用于读取 xml 文件,无法作更新
2. SAX 采用事件处理的方式解析 XML 文件,利用 SAX 解析 XML 文档,涉及两个部分:解析器和事件处理器(对象):解析器可以使用 JAXP 的 API 创建,创建出 SAX 解析器后,就可以指定解析器去解析某个 XML 文档。解析器采用 SAX 方式在解析某个 XML 文档时, 它只要解析到 XML 文档的一个组成部分,都会去调用事件处理器的一个方法, 解析器在调用事件处理器的方法时, 会把当前解析到的xml 文件内容作为方法的参数传递给事件处理器。事件处理器由程序员编写, 程序员通过事件处理器中方法的参数,
就可以很轻松地得到sax 解析器解析到的数据,从而可以决定如何对数据进行处理。
import java.io.InputStream;
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; /**
*
* @version 1L
* @author LinkinPark
* @since 2014-12-26
* @motto 梦似烟花心似水,同学少年不言情
* @desc ^ DefaultHandler:SAX2 事件处理程序的默认基类。
* SAXParserFactory:定义工厂API,使应用程序能够配置和获取基于 SAX 的解析器以解析 XML 文档。
* SAXParser:定义包装 XMLReader 实现类的API。获取此类的实例之后,将可以从各种输入源解析 XML。
* 写此程序旨在理解Java的事件驱动默认,在JavaME编程中这种事件很多的。其实和js和中的事件一样的。
*/
public class LinkinSaxHandler extends DefaultHandler
{ @Override
//接收文档开始的通知。
public void startDocument() throws SAXException
{
super.startDocument();
System.out.println("开始解析XML文档。。。");
} @Override
//接收文档结束的通知。
public void endDocument() throws SAXException
{
super.endDocument();
System.out.println("解析XML文档结束。。。");
} @Override
//接收元素开始的通知。
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
{
super.startElement(uri, localName, qName, attributes);
System.out.println("开始解析元素[" + qName + "]。。。");
System.out.println("共有[" + attributes.getLength() + "]个属性。。。");
for (int i = 0; i < attributes.getLength(); i++)
{
System.out.println("属性名是:"+attributes.getLocalName(i)+";属性值是:"+attributes.getValue(i));
}
} @Override
//接收元素结束的通知。
public void endElement(String uri, String localName, String qName) throws SAXException
{
super.endElement(uri, localName, qName);
System.out.println("解析元素[" + qName + "]结束。。。");
} @Override
//接收元素中字符数据的通知。
public void characters(char[] ch, int start, int length) throws SAXException
{
super.characters(ch, start, length);
String content = new String(ch, start, length);
System.out.println("开始接受元素中的字符串数据。。。");
System.out.println(content);
} public static void main(String[] args) throws Exception
{
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
//使用相对路径来获得一个资源的流
InputStream is = ClassLoader.getSystemResourceAsStream("data-sources.xml");
parser.parse(is, new LinkinSaxHandler());
} }
<?xml version="1.0" encoding="UTF-8"?>
<DataSource>
<database name="mysql" version="5.0">
<driver>com.mysql.jdbc.Driver</driver>
<url>jdbc:mysql://localhost:3306/linkinjdbc</url>
<user>root</user>
<password>root</password>
</database> <database name="Oracle" version="10G">
<driver>oracle.jdbc.driver.OracleDriver</driver>
<url>jdbc:oracle:thin:@127.0.0.1:linkinOracle</url>
<user>system</user>
<password>root</password>
</database>
</DataSource>
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler; public class LinkinSaxHandler extends DefaultHandler
{ /** 基于SAX方式解析XML文档 */
public static void main(String[] args) throws Exception
{
SAXParserFactory factory = SAXParserFactory.newInstance(); //创建SAX解析器工厂
factory.setValidating(true); //让error方法生效
SAXParser parser = factory.newSAXParser(); //生成一个具体的SAX解析器
parser.parse("src/data-sources.xml", new LinkinSaxHandler()); //开始解析
} // 只需覆盖我们感兴趣的方法
private int counter = 0;// 定义一个计数器,保存XML文档触发事件的次数 @Override
// 文档开始事件触发
public void startDocument() throws SAXException
{
counter++;
System.out.println(counter + ".解析XML文件开始...");
} @Override
// 文档结束事件触发
public void endDocument() throws SAXException
{
counter++;
System.out.println("\r\n" + counter + ".解析XML文件结束...");
} @Override
// 元素开始事件触发
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException
{
counter++;
System.out.print(counter + ".<" + qName);
for (int i = 0; i < atts.getLength(); i++)
{ //读取标志的所有属性
System.out.print(" " + atts.getLocalName(i) + "=" + atts.getValue(i));
}
System.out.print(">");
} @Override
// 元素结束事件触发
public void endElement(String uri, String localName, String qName) throws SAXException
{
counter++;
System.out.print(counter + ".</" + qName + ">");
} @Override
// 文本事件触发 打印时尽量不要换行,否则很难看
public void characters(char[] ch, int start, int length) throws SAXException
{
counter++;
String text = new String(ch, start, length); // 当前元素的文本值
System.out.print(counter + ".Text=" + text);
} @Override
//这是可恢复错误。需在SAXParserFactory设置有效性错误才能生效
public void error(SAXParseException e) throws SAXException
{
System.out.println("xml文档有效性错误:" + e);
} @Override
//严重错误
public void fatalError(SAXParseException e) throws SAXException
{
System.out.println("xml文档严重的有效性错误:" + e);
} }
- 三、 比较DOM与SAX:
DOM:处理大型文件时其性能下降的非常厉害。这个问题是由DOM的树结构所造成的,这种结构占用的内存较多,而且DOM必须在解析文件之前把整个文档装入内存,适合对XML的随机访问
优点:1.提供随机定义元素操作,来回移动指针。 2.将整个XML文件一次性加载到内存,形成虚的内存树。
缺点:1.如果XML文件较大,内存空间占用较大。 2.强制将较大的XML文件加载到内存中,有可能损害文件 3.功能通用性
SAX:不同于DOM,SAX是事件驱动型的XML解析方式。它顺序逐行读取XML文件,不需要一次全部装载整个文件。当遇到像文件开头,文档结束,或者标签开头与标签结束时,它会触发一个事件,用户通过在其回调事件中写入处理代码来处理XML文件,适合对 XML的顺序访问
总结:DOM在做CRUD都比较方便,但不适合解析大的XML文档。SAX占用资源比较少,但只适合读取XML。
无废话XML--XML解析(DOM和SAX)的更多相关文章
- JavaEE实战——XML文档DOM、SAX、STAX解析方式详解
原 JavaEE实战--XML文档DOM.SAX.STAX解析方式详解 2016年06月22日 23:10:35 李春春_ 阅读数:3445 标签: DOMSAXSTAXJAXPXML Pull 更多 ...
- XML文件解析DOM解析和SAX解析
解析一个XML文档有哪些内容解析有:dom和sax两种dom:把整个XML文档放入内存,适合XML随机访问,占用内存资源大sax:事件驱动型的XML解析方式,顺序读取,不用一次装载整个文件,遇到标签会 ...
- XML - 十分钟了解XML结构以及DOM和SAX解析方式
引言 NOKIA 有句著名的广告语:"科技以人为本".不论什么技术都是为了满足人的生产生活须要而产生的.详细到小小的一个手机.里面蕴含的技术也是浩如烟海.是几千年来人类科技的结晶, ...
- schema文件及XML文件的DOM和Sax解析
schema文件 <?xml version="1.0" encoding="UTF-8"?> <schema xmlns="htt ...
- Android解析xml文件-采用DOM,PULL,SAX三种方法解析
解析如下xml文件 <?xml version="1.0" encoding="UTF-8"?> <persons> <perso ...
- XML文件的解析—DOM、SAX
一.DOM 解析 思路:获得Document对象,遍历其中节点获得需要的内容 要点: Document : DocuemntBuilderFactory --newDocumentBuilder - ...
- xml它解析----DOM解析
DOM模型(documentobject model) •DOM解析器在解析XML文档时,会把文档中的全部元素,依照其出现的层次关系.解析成一个个Node对象(节点). •在dom中.节点之间关系例如 ...
- :Android网络编程--XML之解析方式:SAX
任何放置在资源(res)目录下的内容可以通过应用程序的R类访问,这是被Android编译过的,而任何放置在资产(assets)目录下的内容会保持它的原始文件格式,为了读取它们,必须使用AssetMan ...
- XML 的解析方法
四种XML解析方法: (1)Dom生成和解析XML文档 *解析器读入整个文档,然后构建一个驻留内存的树结构,然后代码就可以使用 DOM 接口来操作这个树结构. * 优点:整个文档树在内存中,便 ...
随机推荐
- Linux常见命令(用户和组_待补充完善)
添加新用户: useradd [一次性创建新用户账户及设置用户HOME目录结构的简便方法] useradd -D [Linux系统的系统默认值] useradd -m test [创建新用户test目 ...
- select模型
在Windows中所有的socket函数都是阻塞类型的,也就是说只有网络中有特定的事件发生时才会返回,在没有发生事件时会一直等待,虽说我们将它们设置为非阻塞状态,但是在对于服务器段而言,肯定会一直等待 ...
- linked lists in .NET
链表是数据结构中存储数据的一种形式.分为单向链表和双向链表以及循环链表.LinkedList是泛型链表,用节点存取,节点类型为LinkedListNode<T>,每个节点都有Next和Pr ...
- Redis in Docker on Linux Container
记录:在Docker中运行一个Redis实例当我们在Windows系统中安装好Docker以后,在Hyper-V中会自动创建一个Linux虚拟机,如果这个虚拟机没有运行,说明当前运行的是Windows ...
- Gulp 插件及其使用
前端现在有很多的自动打包工具,各有优缺点,而gulp作为其中的一员,也有着很受人们的青睐,简单粗暴,然而gulp本身并没有提供很多的API,真正的一些工作则是靠着插件完成的,本文简单介绍一些常用的gu ...
- promise间隔时间添加dom
<!DOCTYPE html> <html> <head> <title></title> </head> <body&g ...
- 副本机制与副本同步------《Designing Data-Intensive Applications》读书笔记6
进入到第五章了,来到了分布式系统之中最核心与复杂的内容:副本与一致性.通常分布式系统会通过网络连接的多台机器上保存相同数据的副本,所以在本篇之中,我们来展开看看如何去管理和维护这些副本,以及这个过程之 ...
- Python 之 基础知识(一)
首先,对于初学者在一个项目中设置多个程序可以执行,是非常方便的,可以方便对不同知识点的练习和测试 对于商业项目而言,通常在一个项目中,只有一个可以执行的Python程序 一.注释 为了提高可读性,注释 ...
- CCNA笔记(2)
CCNA第一天笔记:何为因特网?答:因特网,是连接各台pc与终端设备,正是因为有了因特网,我们才能与全世界交流,玩在线游戏,在线学习.因特网给我们教育带来什么方便?答:没有了地域的阻止,可以在线学习, ...
- linux(二)之linux常用命令一
linux的命令非常之多,命令多就算了关键每个命令还有很多的参数.不过其实并不要去害怕它.你只要常去用,并且的话,大部分你只要记住命令,参数不记得我们可以去查帮助文档.加油吧!老帖们. 一.登入\登出 ...