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

来源:互联网 发布:js分页代码 编辑:程序博客网 时间:2024/06/05 06:28

                      

XML :可扩展标记语言,XML是一个以文本来描述数据的文档。

XML 用途:

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

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

解析XML文件

1DOM解析:

解析原理: 在处理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;

}

}

 

0 0
原创粉丝点击