一、解析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的代码实现
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 打印所有学生的所有信息
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;
}
}
}
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