您的位置:首页 > 编程语言 > Java开发

java 解析XML文件(DOM & SAX)(一)

2015-12-10 16:47 615 查看
XML :可扩展标记语言,XML是一个以文本来描述数据的文档。

XML 用途:

1:充当显示数据。2:XML描述数据并在联系服务器系统的其余部分之间传递。

XML 是信息封装,和消息传递技术。

解析XML文件

1:DOM解析:

解析原理: 在处理DOM解析的时候,需要读入整个XML文档,然后在内存中创建DOM树,生成DOM树的每个NODE对象,当文档相对较小的时候,不会出现问题,当文档一旦较大,处理DOM就会相当费时,特别是其对内存的需求,也将成倍增加,以至于在某些应用中使用DOM是不划算的。

实例如下:

Person.xml 文件如下:

<?xml version="1.0" encoding="UTF-8"?>

<codinkge>

<Person personid="1">

<name> 杨跟超</name>

<age>18</age>

<sex> 男 </sex>

<tel>11129290900</tel>

</Person>

<Person personid="2">

<name> 王建</name>

<age>18</age>

<sex> 男 </sex>

<tel>11129290900</tel>

</Person>

</codinkge>

创建一个Person类,属性包含xml文件中的各个属性 此处省略(生成Seter ,Geter 方法 构造方法,toString方法等)

主程序如下:

public class DOMforXML {

public static void main(String[] args) {

List <Person> p=parseDomXML();

for (Person person :p){

System.out.println(person);

}

}

private static List <Person> parseDomXML() {

List <Person> list = new ArrayList<Person>();

Person p = null;

// 创建一个文档解析工厂

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

// 创建文档解析器

DocumentBuilder builder;

try {

builder = factory.newDocumentBuilder();

InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/xiyou/Person.xml");

Document doc =builder.parse(is); // 将XML文件的输入流放入解析器中解析

// 从解析器中获取数据 (根据标签获得消息)

NodeList personlist= doc.getElementsByTagName("Person"); // 获取两个Person节点

for (int j = 0 ;j <personlist.getLength();j++){

Node presonNode = personlist.item(j);

p= new Person();

String id = presonNode.getAttributes().getNamedItem("personid").getNodeValue(); // 获取ID

p.setPersonid(id);

NodeList childs = presonNode.getChildNodes();// 获取根结点person下的所有子节点

for (int k = 0 ; k <childs.getLength() ;k++){

Node childNode =childs.item(k);

String name = childNode.getNodeName();

if ("name".equals(name)){

/*<name> 杨跟超</name> 杨跟超 相当于<name>标签的第一个节点

*/

p.setName(childNode.getFirstChild().getNodeValue());

}else if ("age".equals(name)){

p.setAge(Integer.parseInt(childNode.getFirstChild().getNodeValue()));

}else if ("sex".equals(name)){

p.setSex(childNode.getFirstChild().getNodeValue());

}else if ("tel".equals(name)){

p.setTel(Long.parseLong(childNode.getFirstChild().getNodeValue()));

}

}

list.add(p);

}

} catch (ParserConfigurationException e) {

e.printStackTrace();

} catch (SAXException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

return list;

}

}

DOM解析的优缺点:

优点:1:由于整棵树在内存中,因此对xml文档随机访问 2:对XML文档进行修改

缺点 2: 整个文档必须一次解析完,2:由于真个文档都需要载入内存,对于大文档成本较高。

SAX 解析XML

由于DOM在解析XML的时候将整个XML文档读入内存,因此存在缺陷。SAX不同于DOM的文档驱动,它是事件驱动,也就是说它并不需要读入整个文档,而读入文档的过程就是SAX解析的过程,事件驱动是指一种基于回调机制的程序运行方法,在XMLReader接受XML文档的过程中就进行解析,就是读入的文档的过程就是解析的过程。适用于较大的只读文档。

在Sax的解析过程中,读取到文档开头、结尾,元素的开头和结尾都会触发一些回调方法,你可以在这些回调方法中进行相应事件处理

这四个方法是:startDocument() 、 endDocument()、 startElement()、 endElement

此外,光读取到节点处是不够的,还需要characters()方法来仔细处理元素内包含的内容

将这些回调方法集合起来,便形成了一个类,这个类也就是我们需要的触发器

一般从Main方法中读取文档,却在触发器中处理文档,这就是所谓的事件驱动解析方法



如上图在触发器中首先开始读取文档,然后逐个解析元素,每个元素中的内容会返回到characters ()方法,接着结束元素读取,所有元素读取完后,结束文档解析,

实例如下: 创建触发器类:

创建触发器类首先要继承DefaultHandler并重写响应的方法

public class PersonHandler extends DefaultHandler{

private List <Person > person;

private Person p ;

private String tag;//标记标签的名称

public List<Person> getPerson() {

return person;

}

@Override

// 开始文档解析

public void startDocument() throws SAXException {

super.startDocument();

person = new ArrayList<Person>();

System.out.println("开始解析文档。。。。。。");

}

@Override

// 开始解析标签, 形如<name> <sex>的标签为开始标签

public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

super.startElement(uri, localName, qName, attributes);

if ("Person".equals(qName)){

p = new Person ();

p.setPersonid(attributes.getValue("personid"));

}

tag = qName;

}

@Override

//处理文本内容包括空格

public void characters(char[] ch, int start, int length) throws SAXException {

super.characters(ch, start, length);

if (tag!=null){

if ("name".equals(tag)){

p.setName(new String (ch, start , length));

}else if ("age".equals(tag)){

p.setAge(Integer.parseInt(new String (ch, start, length)));

}else if ("sex".equals(tag)){

p.setSex(new String (ch, start, length));

}else if ("tel".equals(tag)){

p.setTel(Long.parseLong(new String (ch , start,length)));

}

}

}

@Override

// 结束标签解析

public void endElement(String uri, String localName, String qName) throws SAXException {

super.endElement(uri, localName, qName);

if ("Person".equals(qName)){

person.add(p);// 将Person对象添加到列表中

}

tag = null;

}

@Override

// 结束文档解析

public void endDocument() throws SAXException {

super.endDocument();

System.out.println("文档解析完毕!!!!!");

}

}

Xml文档 (与上DOM解析同一个XML文档)

创建一个Person类,属性包含xml文件中的各个属性 此处省略(生成Seter ,Geter 方法 构造方法,toString方法等)

解析如下:

package com.xiyou;

import java.io.IOException;

import java.io.InputStream;

import java.util.ArrayList;

import java.util.List;

import javax.xml.parsers.ParserConfigurationException;

import javax.xml.parsers.SAXParser;

import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

public class SAXUSE {

public static void main(String[] args) {

List <Person> list = parseSAXxml ();

for (Person person : list){

System.out.println(person);

}

}

private static List <Person> parseSAXxml() {

List <Person> list = null;

// 创建解析器工厂

SAXParserFactory factory = SAXParserFactory.newInstance();

try {

// 生成一个sax解析器

SAXParser parser = factory.newSAXParser();

InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/xiyou/Person.xml");

PersonHandler dh = new PersonHandler();

try {

parser.parse(is, dh);//解析

list=dh.getPerson();

} catch (IOException e) {

e.printStackTrace();

}

} catch (ParserConfigurationException e) {

e.printStackTrace();

} catch (SAXException e) {

e.printStackTrace();

}

return list;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: