Java中使用Dom和Sax两种思想解析XML

本文介绍了DOM和SAX两种常见的XML解析方法,通过实例详细展示了这两种方法的代码实现过程及优缺点。DOM将XML文档全部加载到内存,便于操作但占用资源较多;SAX采用事件驱动方式,适合大型文件解析。

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

一、解析XML的两种常见思路

注意:该博客学习参考自《黑马JavaEE12期》


解析XML的两种常见思想:

DOM:将XML文档中所有内容都封装成对象,读取时,将所有对象都加载到内存中,在内存中创建一颗DOM树(记录对象间的关系)。

         优点:方便的进行增删查改

         缺点:内存占用小

SAX:事件驱动的,与pull解析类似。把xml文档的读取过程,划分出5类事件。我们只要提供遇到每类事件做什么的锦囊即可。

       优点:内存占用小。

       缺点:不能进行增删改的操作。

 

DOM解析是由w3c推荐提出的.。

Sax解析是由民间提出的。


二、Dom和Sax解析XML具体代码实现

2.1 准备待解析的XML文档

新建一个普通的Java Project,并且在src目录下新建students.xml,内容如下

<?xml version="1.0" encoding="utf-8" ?>
<students>
	<student number="itcast_0001">
		<name>tom</name>
		<age>18</age>
		<sex>male</sex>
	</student>
	<student number="itcast_0002">
		<name>jerry</name>
		<age>16</age>
		<sex>female</sex>
	</student>
</students>

2.2 Dom的代码实现

1、编写代码解析students.xml
package cn.itcast.dom;

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.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * 使用DOM思想解析XML
 */
public class Demo1 {
	public static void main(String[] args) {
		//1、获得jaxp工厂
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		try {
			//2、通过工厂获得解析器实现类
			DocumentBuilder builder = factory.newDocumentBuilder();
			//3、使用解析器加载XML文档==>document
			Document doc = builder.parse(new File("src/students.xml"));
			//获取所有学生元素的集合
			NodeList studentList = doc.getElementsByTagName("student");
			//遍历集合
			for(int i = 0; i < studentList.getLength(); i ++) {
				Element stuEle = (Element) studentList.item(i);
				//获得学生元素的number属性
				String number = stuEle.getAttribute("number");
				System.out.println("学生的学号是:" + number);
				//获得学生结点下的所有子节点(包括文本在内一个7个)
				NodeList children = stuEle.getChildNodes();
				//遍历集合并提取我们想要的name age sex元素对象
				for (int x = 0; x < children.getLength(); x ++) {
					Node node = children.item(x);
					//判断是否是自己想要的类型
					/* 方式一
					 * if(node instanceof Element){
						
					}*/
					/**
					 * 方式2:
					 */
					if(node.getNodeType() == Node.ELEMENT_NODE) {
						Element child = (Element) node;
						if("name".equals(child.getNodeName())) {
							String name = child.getTextContent();
							System.out.println("学生的姓名是:" + name);
						} else if("age".equals(child.getNodeName())) {
							String age = child.getTextContent();
							System.out.println("学生的年龄是:" + age);
						} else if("sex".equals(child.getNodeName())) {
							String sex = child.getTextContent();
							System.out.println("学生的性别是:" + sex);
						}
					}
				}
			}
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

2、运行上述代码,控制打印如下内容

学生的学号是:itcast_0001

学生的姓名是:tom

学生的年龄是:18

学生的性别是:male

学生的学号是:itcast_0002

学生的姓名是:jerry

学生的年龄是:16

学生的性别是:female

2.3 Sax的代码实现

要理解下面的代码,先要理解SAX解析XML的原理。SAX是基于事件驱动的,与pull解析类似。把xml文档的读取过程,划分出5类事件:文档开始事件、文档结束事件、元素开始事件、元素结束事件和遇到文本(字符)事件。当每个事件发生时,都会调用对应的方法。


2.3.1 打印所有学生的所有信息

1、自定义一个默认的处理器MyHandler,继承DefaultHandler


package cn.itcast.sax;

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

/**
 * 自定义处理器,获得所有学生,打印信息
 */
public class MyHandler extends DefaultHandler {
	
	/**
	 * 文档开始事件
	 */
	@Override
	public void startDocument() throws SAXException {
		System.out.println("文档开始解析啦!");
	}
	
	/**
	 * 遇到所有的元素开始都会触发该方法,
	 * sax 1.0版本中前两个参数没有用,永远是null.
	 * 参数3 qName 告知开发者当前触发的元素是哪个元素
	 * 参数4 将标签上的属性提供给你
	 */
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		System.out.println(qName + "元素开始啦!");
		//判断当前遇到的元素是否是student元素
		if("student".equals(qName)) {
			//获取number属性
			String number = attributes.getValue("number");
			System.out.println("学生的学号是:" + number);
		}
	}
	
	/**
	 * 对应XML文档中的文本
	 */
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		String str = new String(ch, start, length);
		str = str.trim();//去掉两端空白字符 回车 空格 制表
		if(str.length() > 0) {
			System.out.println(str);
		}
	}

	/**
	 * 对应某个元素的结束
	 * 参数3 qName 代表的是当前的元素
	 */
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		System.out.println(qName + "元素结束啦!");
	}

	
	@Override
	public void endDocument() throws SAXException {
		System.out.println("文档结束解析啦!");
	}
}

2、定义测试类解析XML文档

package cn.itcast.sax;

import java.io.File;
import java.io.IOException;

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

import org.xml.sax.SAXException;

/**
 * 使用Sax思想解析XML
 */
public class Demo1 {

	public static void main(String[] args) {
		//1、获得解析器工厂
		SAXParserFactory factory = SAXParserFactory.newInstance();
		try {
			//2、获得解析器
			SAXParser parser = factory.newSAXParser();
			//3、解析文档
			parser.parse(new File("src/students.xml"), new MyHandler());
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

3、运行Demo1.java中的代码,得出如下结果


student元素结束啦!

student元素开始啦!

学生的学号是:itcast_0002

name元素开始啦!

jerry

name元素结束啦!

age元素开始啦!

16

age元素结束啦!

sex元素开始啦!

female

sex元素结束啦!

student元素结束啦!

students元素结束啦!

文档结束解析啦!


2.3.2 打印指定学号学生的所有信息

1、自定义MyHandler2,继承DefaultHandler


package cn.itcast.sax;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
 * 获得指定学号的学生的所有信息
 */
public class MyHandler2 extends DefaultHandler {
	private String number;
	
	public MyHandler2(String number) {
		super();
		this.number = number;
	}

	private boolean flag = false;
	private String current = "";


	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		current = qName;
		if(qName.equals("student")&&attributes.getValue("number").equals(number)){
			flag = true;
		}
	}
	
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		String str = new String(ch,start,length);
		str = str.trim();
		if(flag && str.length()>0){
			if(current.equals("name")){
				System.out.println("学生的姓名是:"+str);
			}else if(current.equals("age")){
				System.out.println("学生的年龄是:"+str);
			}else if(current.equals("sex")){
				System.out.println("学生的性别是:"+str);
			}
			
		}
		
	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		if(qName.equals("student")){
			flag = false;
		}
	}

}


2、修改Demo1.java中的代码如下

package cn.itcast.sax;

import java.io.File;
import java.io.IOException;

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

import org.xml.sax.SAXException;

/**
 * 使用Sax思想解析XML
 */
public class Demo1 {

	public static void main(String[] args) {
		//1、获得解析器工厂
		SAXParserFactory factory = SAXParserFactory.newInstance();
		try {
			//2、获得解析器
			SAXParser parser = factory.newSAXParser();
			//3、解析文档
			parser.parse(new File("src/students.xml"),
					new MyHandler2("itcast_0002"));
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

3、运行上面的代码,控制台打印如下信息

学生的姓名是:jerry

学生的年龄是:16

学生的性别是:female




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值