*1 dom4j解析器
1)CRUD的含义:CreateReadUpdateDelete增删查改
2)XML解析器有二类,分别是DOM和SAX(simple Api for xml)。
a)DOM一次性将整个XML文件读到内存,形成一个倒状的树形结构
b)SAX多次将整个XML文件读到内存
c)Document对象代表XML文件在内存中的映像
3)常用的API如下:
SAXReader saxReader = new SAXReader(); SAXReader是dom4j的核心类
Document document = saxReader.read("*.xml")
Document.getRootElement()
Element.getName()
Element.elements():取得该元素下的所有直接子元素
Element.elementText():从一个元素导航到另一个元素且取出该元素的文本
Element.element("车牌") :从一个元素导航到另一个元素
Element.attributeValue("出产时间"):取得一个元素对应的属性
Element.addElement("单价").setText("40"):添加新元素,同时设置该元素文本的值
OutputFormat format = OutputFormat.createPrettyPrint():使用缩格形式写XML文件
XMLWriter xmlWriter = new XMLWriter(os,format):构造XML写入器
xmlWriter.write(document):将内存中的document对象写入硬盘
firstCarElement.remove(firstCarPriceElement):从直接父元素删除直接子元素
//firstCarPriceElement.getParent().remove(firstCarPriceElement):从直接父元素删除直接子元素
package cn.itcast.xml.dom4j; public class Car implements Comparable<Car>{
private String band;//车牌
private String place;//产地
private String time;//出产时间
private int price;//单价
public Car(){}
public String getBand() {
return band;
}
public void setBand(String band) {
this.band = band;
}
public String getPlace() {
return place;
}
public void setPlace(String place) {
this.place = place;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int compareTo(Car car) {
if(this.price<car.getPrice()){
return 1;
}else if(this.price>car.getPrice()){
return -1;
}else{
return 0;
}
}
}
package cn.itcast.xml.dom4j; import java.io.File;
import java.util.List; import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
//基于DOM4J解析XML文件(read)[dom4j-1.6.1.jar]
//使用dom4j解析xml文件
public class Demo1 {
public static void main(String[] args) throws Exception {
//创建dom4j解析器
SAXReader saxReader = new SAXReader();
//加载需要解析的xml文件
Document document = saxReader.read(new File("src/cn/itcast/xml/dom4j/car.xml"));
//取得根元素
Element rootElement = document.getRootElement();
//显示根元素的名称
System.out.println(rootElement.getName());
//取得根元素下的子元素
List<Element> elementList = rootElement.elements();
System.out.println("共有" + elementList.size()+"辆车");
for(Element e : elementList){
System.out.println("车牌:" + e.elementText("车牌"));
System.out.println("产地:" + e.elementText("产地"));
System.out.println("出产时间:" + e.element("车牌").attributeValue("出产时间"));
System.out.println("------------------------------");
}
}
}
package cn.itcast.xml.dom4j; import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.junit.Test; //使用dom4j操作xml文件的cud
public class Demo2 {
@Test
public void create() throws Exception{
Document document = getDocument();
Element rootElement = document.getRootElement();
//取得第一辆汽车
Element firstCarElement = (Element) rootElement.elements().get(0);
//添加新元素"单价",并设置文本为30
firstCarElement.addElement("单价").setText("40");
//将内存中的xml文件写到硬盘中
write2xml(document);
}
private void write2xml(Document document) throws Exception {
OutputFormat format = OutputFormat.createPrettyPrint();
OutputStream os = new FileOutputStream("src/cn/itcast/xml/dom4j/car.xml");
XMLWriter xmlWriter = new XMLWriter(os,format);
xmlWriter.write(document);
xmlWriter.close();
}
private Document getDocument() throws Exception {
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File("src/cn/itcast/xml/dom4j/car.xml"));
return document;
}
@Test
public void update() throws Exception{
Document document = getDocument();
Element rootElement = document.getRootElement();
Element firstCarElement = (Element) rootElement.elements().get(0);
firstCarElement.element("单价").setText("60");
write2xml(document);
}
@Test
public void delete() throws Exception{
Document document = getDocument();
Element rootElement = document.getRootElement();
Element firstCarElement = (Element) rootElement.elements().get(0);
Element firstCarPriceElement = firstCarElement.element("单价");
firstCarElement.remove(firstCarPriceElement);
//firstCarPriceElement.getParent().remove(firstCarPriceElement);
write2xml(document);
}
}
package cn.itcast.xml.dom4j; import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
//课堂练习(将car.xml文件中的所有car元素解析出存入集合,并按照单价对集合中的元素降序后输出)
public class Demo3 {
public static void main(String[] args) throws Exception {
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File("src/cn/itcast/xml/dom4j/car.xml"));
List<Element> elementList = document.getRootElement().elements();
List<Car> carList = new ArrayList<Car>();
for(Element e : elementList){
Car car = new Car();
car.setBand(e.elementText("车牌"));
car.setPlace(e.elementText("产地"));
car.setTime(e.element("车牌").attributeValue("出产时间"));
car.setPrice(Integer.parseInt(e.elementText("单价")));
carList.add(car);
}
//System.out.println("按单价排序前:");
//show(carList);
System.out.println("按单价排序后:");
sortByPriceDesc(carList);
}
public static void sortByPriceDesc(List<Car> carList) {
Collections.sort(carList);
show(carList);
}
public static void show(List<Car> carList){
if(carList!=null && carList.size()>0){
for(Car car : carList){
System.out.print("车牌:"+car.getBand()+"\t");
System.out.print("产地:"+car.getPlace()+"\t");
System.out.print("单价:"+car.getPrice()+"\t");
System.out.println("出产时间:"+car.getTime());
}
}
}
}
package cn.itcast.xml.dom4j; import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.List; import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter; //使用dom4j其它的API
public class Demo4 {
public static void main(String[] args) throws Exception { /*String->XML
String text = "<root><res>这是根元素</res></root>";
Document document = DocumentHelper.parseText(text);
OutputFormat format = OutputFormat.createPrettyPrint();
OutputStream os = new FileOutputStream("src/cn/itcast/xml/dom4j/string2xml.xml");
XMLWriter xmlWriter = new XMLWriter(os,format);
xmlWriter.write(document);
xmlWriter.close();
*/ /*创建空XML文件
Document document = DocumentHelper.createDocument();
document.addElement("root").setText("这是根元素");
OutputFormat format = OutputFormat.createPrettyPrint();
OutputStream os = new FileOutputStream("src/cn/itcast/xml/dom4j/empty.xml");
XMLWriter xmlWriter = new XMLWriter(os,format);
xmlWriter.write(document);
xmlWriter.close();
*/ /*指定插入次序,默认插入到最后
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File("src/cn/itcast/xml/dom4j/car.xml"));
List<Element> elementList = document.getRootElement().elements();
Element newCarElement = DocumentHelper.createElement("汽车");
newCarElement.setText("这是我的汽车");
elementList.add(1,newCarElement);
OutputFormat format = OutputFormat.createPrettyPrint();
OutputStream os = new FileOutputStream("src/cn/itcast/xml/dom4j/car.xml");
XMLWriter xmlWriter = new XMLWriter(os,format);
xmlWriter.write(document);
xmlWriter.close();
*/ //XML->String
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File("src/cn/itcast/xml/dom4j/car.xml"));
Element rootElement = document.getRootElement();
Element firstCarElement = (Element) rootElement.elements().get(0);
String xml = firstCarElement.asXML();
System.out.println(xml);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<车辆清单>
<汽车>
<车牌 出产时间="2010年">奥迪</车牌>
<产地>北京</产地>
<单价>30</单价>
</汽车>
<汽车>
<车牌 出产时间="2011年">本田</车牌>
<产地>广州</产地>
<单价>60</单价>
</汽车>
</车辆清单>
<?xml version="1.0" encoding="UTF-8"?> <root>这是根元素</root>
<?xml version="1.0" encoding="UTF-8"?>
<root>
<res>这是根元素</res>
</root>
*2 基于dom4j的xpath技术
1)能够在xml文件中,快速定位需要元素,无需从根元素一个一个的导航到需要的子元素
Document.selectNodes():取得所有符合xpath格式的元素
Document.selectSingleNode():取得所有符合xpath格式的元素的第一个元素
Node类型是Element/Text/Attribute/Document/...类型的父接口
package cn.itcast.xml.xpath; import java.io.File;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader; //使用Xpath,取得第二辆汽车的产地[dom4j-1.6.1.jar和jaxen-1.1-beta-6.jar]
public class Demo1 {
public static void main(String[] args) throws Exception {
SAXReader reader = new SAXReader();
Document document = reader.read(new File("src/cn/itcast/xml/xpath/car.xml"));
String xpath = "//单价";
Element element = (Element) document.selectSingleNode(xpath);
System.out.println("第一辆汽车的单价是:" + element.getText()); //List<Element> elementList = document.selectNodes(xpath);
//System.out.println("第二辆汽车的单价是:" + elementList.get(1).getText());
}
}
<?xml version="1.0" encoding="UTF-8"?>
<车辆清单>
<汽车>
<车牌 出产时间="2010年">奥迪</车牌>
<产地>北京</产地>
<单价>30</单价>
</汽车>
<汽车>
<车牌 出产时间="2011年">本田</车牌>
<产地>广州</产地>
<单价>60</单价>
</汽车>
</车辆清单>
package cn.itcast.xml.xpath; import java.io.File;
import java.util.Scanner;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader; //使用Xpath,模拟用户登录
public class Demo2 {
public static void main(String[] args) throws Exception { //读取用户在键盘的输入信息
Scanner scanner = new Scanner(System.in);
System.out.print("用户名:");
String username = scanner.nextLine();
System.out.print("密码:");
String password = scanner.nextLine(); //解析XML文件,并查询指定的元素
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File("src/cn/itcast/xml/xpath/users.xml"));
String xpath = "//user[@username='"+username+"' and @password='"+password+"']";
Element element = (Element) document.selectSingleNode(xpath); //输出结果
if(element!=null){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<root>
<user id="u01" username="jack" password="123456"/>
<user id="u02" username="marry" password="654321"/>
</root>
3 简单工厂设计模式
1)目的就是统一管理访问层的所有Dao,让Service在Dao的处理上相对独立
2)引用DaoFactory来管理所有的具体Dao,并采用单例模式限制DaoFactory的个数
package cn.itcast.xml.model; //单例的Dao工厂
public class DaoFactory { //NO1
private DaoFactory(){} //NO2
public static DaoFactory getDaoFactory(){
if(daoFactory==null){
daoFactory = new DaoFactory();
}
return daoFactory;
} //NO3
private static DaoFactory daoFactory; public IDao getDao(){
return new DaoJdbc();
}
}
package cn.itcast.xml.model; public class DaoHibernate implements IDao {
public void create() {
System.out.println("DaoHibernate::create()");
}
}
package cn.itcast.xml.model; //访问层
public class DaoJdbc implements IDao{
public void create(){
System.out.println("DaoJdbc::create()");
}
}
package cn.itcast.xml.model; public interface IDao {
public void create();
}
package cn.itcast.xml.model; //业务层(不变)
public class Service {
public void create(){
DaoFactory daoFactory = DaoFactory.getDaoFactory();
IDao iDao = daoFactory.getDao();
iDao.create();
}
}
package cn.itcast.xml.model; //表现层
public class Demo1 {
public static void main(String[] args) {
Service service = new Service();
service.create();
}
}
4 分层结构设计思想
1)将各个不同功能的代码块,分离出来,避免不同功能的代码耦合,为程序扩展和维护提供方便。
package cn.itcast.xml.example1;
//(分层结构):模拟用户登录
import java.io.File; import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader; public class LoginBusiness {
//测试
public static void main(String[] args) throws Exception { LoginUI loginUI = new LoginUI();
LoginBusiness lognBusiness = new LoginBusiness(); User user = loginUI.input();
boolean flag = lognBusiness.check(user); loginUI.output(flag); }
//判段
public boolean check(User user) throws Exception{
boolean flag = false;
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File("src/cn/itcast/xml/xpath/users.xml"));
String xpath = "//user[@username='"+user.getUsername()+"' and @password='"+user.getPassword()+"']";
Element element = (Element) document.selectSingleNode(xpath);
if(element!=null){
flag = true;
}
return flag;
}
}
package cn.itcast.xml.example1; import java.util.Scanner; //输入输出
public class LoginUI {
public User input(){
User user = new User();
Scanner scanner = new Scanner(System.in);
System.out.print("用户名:");
String username = scanner.nextLine();
System.out.print("密码:");
String password = scanner.nextLine();
user.setUsername(username);
user.setPassword(password);
return user;
}
public void output(boolean flag){
if(flag){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
}
}
package cn.itcast.xml.example1; public class User {
private String id;
private String username;
private String password;
public User(){}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<root>
<user id="u01" username="jack" password="123456"/>
<user id="u02" username="marry" password="654321"/>
</root>
*5 案例
1)以分层思想,模拟用户登录
2)通过配置文件解析/反射/运行某个类的方法
<?xml version="1.0" encoding="UTF-8"?>
<root>
<class>
<className>cn.itcast.xml.example2.Person</className>
<methodName>jump</methodName>
<argType>java.lang.String</argType>
<argValue>李四</argValue>
</class>
</root>
package cn.itcast.xml.example2; public class Person {
public void run(String who){
System.out.println("Person::run():" + who);
}
public void jump(String who){
System.out.println("Person::jump():" + who);
}
}
package cn.itcast.xml.example2; import java.io.File;
import java.lang.reflect.Method;
import org.dom4j.Document;
import org.dom4j.io.SAXReader; //基于XML配置文件,解析,反射,运行程序
public class Demo1 {
public static void main(String[] args) throws Exception {
//解析xml文件
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File("src/cn/itcast/xml/example2/config.xml"));
String className = document.selectSingleNode("//className").getText();
String methodName = document.selectSingleNode("//methodName").getText();
String argType = document.selectSingleNode("//argType").getText();
String argValue = document.selectSingleNode("//argValue").getText(); //反射创建对象并执行方法
Class clazz = Class.forName(className);
Method method = clazz.getMethod(methodName,Class.forName(argType));
method.invoke(clazz.newInstance(),argValue);
}
}
3)分层结构的学员信息案例
dao
package cn.itcast.xml.example3.dao; import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import cn.itcast.xml.example3.domain.Student; public class StudentDao {
//根据编号更新学员信息
public void update(Student student) throws Exception {
Document document = getDocument();
String xpath = "//student[@id='"+student.getId()+"']";
Element element = (Element) document.selectSingleNode(xpath);
if(element!=null){
element.element("name").setText(student.getName());
element.element("age").setText(student.getAge());
write2xml(document);
}else{
System.out.println("查无此学员");
} }
//根据编号显示学员信息
public void read(String id) throws Exception{
Document document = getDocument();
String xpath = "//student[@id='"+id+"']";
Element element = (Element) document.selectSingleNode(xpath);
if(element!=null){
System.out.println("编号:" + element.attributeValue("id"));
System.out.println("姓名:" + element.elementText("name"));
System.out.println("年龄:" + element.elementText("age"));
}else{
System.out.println("查无此学员");
}
}
//根据编号删除某位学员的信息
public void delete(String id) throws Exception{
Document document = getDocument();
String xpath = "//student[@id='"+id+"']";
Element element = (Element) document.selectSingleNode(xpath);
if(element!=null){
element.getParent().remove(element);
write2xml(document);
}else{
System.out.println("查无此学员");
}
}
//增加学员的信息
public boolean create(Student student) throws Exception{
boolean flag = false;
if(student!=null){
Document document = null;
try {
document = getDocument();
} catch (Exception e) {
//创建空XML文件
document = DocumentHelper.createDocument();
//创建<students>根元素
document.addElement("students");
}
Element rootElement = document.getRootElement();
Element studentElement = rootElement.addElement("student");
studentElement.addAttribute("id",student.getId());
studentElement.addElement("name").setText(student.getName());
studentElement.addElement("age").setText(student.getAge());
write2xml(document);
flag = true;
}
return flag;
}
//将内存中的Document写到硬盘
private void write2xml(Document document) throws Exception {
OutputFormat format = OutputFormat.createPrettyPrint();
OutputStream os = new FileOutputStream("src/cn/itcast/xml/example3/db/students.xml");
XMLWriter xmlWriter = new XMLWriter(os,format);
xmlWriter.write(document);
xmlWriter.close();
}
//取得Document对象
private Document getDocument() throws Exception {
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File("src/cn/itcast/xml/example3/db/students.xml"));
return document;
} }
domain
package cn.itcast.xml.example3.domain; public class Student {
private String id;
private String name;
private String age;
public Student(){}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) throws Exception {
if(name.matches("[a-zA-Z]+")){
this.name = name;
}else{
throw new Exception();
}
}
public String getAge() {
return age;
}
public void setAge(String age) throws Exception {
if(age.matches("[0-9]+")){
this.age = age;
}else{
throw new Exception();
}
}
}
ui
package cn.itcast.xml.example3.ui; import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter; //id的自增长
public class IdUtil {
public static String getId() throws Exception{
BufferedReader br = new BufferedReader(new FileReader("src/cn/itcast/xml/example3/ui/id.txt"));
String id = br.readLine();//"2011100801"(字符串)
int temp = Integer.parseInt(id)+1;//2011100802(int型)
BufferedWriter bw = new BufferedWriter(new FileWriter("src/cn/itcast/xml/example3/ui/id.txt"));
bw.write(temp+"");
bw.flush();
bw.close();
return id;
}
}
package cn.itcast.xml.example3.ui; import java.util.Scanner;
import cn.itcast.xml.example3.dao.StudentDao;
import cn.itcast.xml.example3.domain.Student; public class StudentUI {
public static void main(String[] args) throws Exception {
input();
}
public static void input() throws Exception{ Scanner scanner = new Scanner(System.in);
System.out.print("学员的编号:");
String id = scanner.nextLine();
System.out.print("更新学员的姓名:");
String name = scanner.nextLine();
System.out.print("更新学员的年龄:");
String age = scanner.nextLine();
Student student = new Student();
student.setId(id);
student.setName(name);
student.setAge(age);
StudentDao studentDao = new StudentDao();
studentDao.update(student); /*键盘输入学员信息
Scanner scanner = new Scanner(System.in);
System.out.print("查询学员的编号:");
String id = scanner.nextLine();
StudentDao studentDao = new StudentDao();
studentDao.read(id);
Scanner scanner = new Scanner(System.in);
System.out.print("删除学员的编号:");
String id = scanner.nextLine();
StudentDao studentDao = new StudentDao();
studentDao.delete(id);
Scanner scanner = new Scanner(System.in);
System.out.print("用户名:" );
String name = scanner.nextLine();
System.out.print("年龄:" );
String age = scanner.nextLine();
//封装成JavaBean对象
Student student = new Student();
student.setId(IdUtil.getId());
student.setName(name);
student.setAge(age);
//调用Dao对象
StudentDao studentDao = new StudentDao();
boolean flag = studentDao.create(student);
if(flag){
System.out.println("操作成功");
}else{
System.out.println("操作失败");
}
*/
}
}
db
<?xml version="1.0" encoding="UTF-8"?> <students>
<student id="2011100801">
<name>keke</name>
<age>11</age>
</student>
</students>
6 SAX解析器
1)sun公司提供的一个基于事件的xml解析器
2)SAXParser是SAX解析器的核心类,在使用过程中,需要一个SAX处理器,该处理器必须扩展DefaultHandler
3)SAX解析器在解析XML文件时,会根据XML文件此时的状态,即开始标签,结束标签,调用SAX处理器对应的方法
4)SAX解析器在解析XML文件时,自动导航,无需像dom4j一样,人为导航
5)SAX解析器会将空白字符当作一个有效字符对待
package cn.itcast.xml.sax; import java.io.File;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler; //使用sax解析器解析xml文件
public class Demo1 {
public static void main(String[] args) throws Exception {
//创建SAX解析器工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
//创建SAX解析器
SAXParser saxParser = factory.newSAXParser();
//加载xml文件
saxParser.parse(
new File("src/cn/itcast/xml/sax/car.xml"),
new MyHandler());
}
}
//自定义SAX处理器
class MyHandler extends DefaultHandler{
private long begin;
public void startDocument(){
System.out.println("解析XML文件开始");
begin = System.currentTimeMillis();
}
public void endDocument() {
System.out.println("解析XML文件结束");
long end = System.currentTimeMillis();
System.out.println("解析XML共用" + (end-begin) + "毫秒");
}
public void startElement(
String uri,
String localName,
String qName,
Attributes attributes){
System.out.println("<"+qName+">");
System.out.println("有"+attributes.getLength()+"个属性");
System.out.println(attributes.getValue("出产时间"));
}
public void endElement(
String uri,
String localName,
String qName){
System.out.println("</"+qName+">");
}
public void characters(
char[] ch,
int start,
int length){
String content = new String(ch,start,length);
if(content.trim().length()>0){
System.out.println(content);
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<车辆清单>
<汽车>
<车牌 出产时间="2011年">奥迪</车牌>
<产地>北京</产地>
<单价>30</单价>
</汽车>
</车辆清单>
SAX采用事件处理的方式解析XML文件,利用 SAX 解析 XML 文档,涉及两个部分:解析器和事件处理器:
•解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。
•解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。
•解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。
阅读DefaultHandler API文档,常用方法:startElement、endElement、characters
使用JAXP进行DOM解析
javax.xml.parsers 包中的DocumentBuilderFactory用于创建DOM模式的解析器对象,DocumentBuilderFactory是一个抽象工厂类,它不能直接实例化,但该类提供了一个newInstance方法,这个方法会根据本地平台默认安装的解析器,自动创建一个工厂的对象并返回。
获得JAXP中的DOM解析器
- 调用 DocumentBuilderFactory.newInstance() 方法得到创建 DOM 解析器的工厂。
- 调用工厂对象的 newDocumentBuilder方法得到 DOM 解析器对象。
- 调用 DOM 解析器对象的 parse() 方法解析 XML 文档,得到代表整个文档的 Document 对象,从而可以利用DOM特性对整个XML文档进行操作了。
DOM编程
lDOM模型(Document Object Model)
•DOM解析器在解析XML文档时,会把文档中的所有元素,按照其出现的层次关系,解析成一个个Node对象(节点)。
•在DOM中,节点之间关系如下:
•位于一个节点之上的节点是该节点的父节点(parent)
•一个节点之下的节点是该节点的子节点(children)
•同一层次,具有相同父节点的节点是兄弟节点(sibling)
•一个节点的下一个层次的节点集合是节点后代(descendant)
•父、祖父节点及所有位于节点上面的,都是节点的祖先(ancestor)
•节点类型(下页ppt)
Node对象
Node对象提供了一系列常量来代表结点的类型,当开发人员获得某个Node类型后,就可以把Node节点转换成相应的节点对象(Node的子类对象),以便于调用其特有的方法。(查看API文档)
Node对象提供了相应的方法去获得它的父结点或子结点。编程人员通过这些方法就可以读取整个XML文档的内容、或添加、修改、删除XML文档的内容了。
DOM方式解析XML文件(XML文件最好是有效的)
•遍历所有节点
•查找某一个节点
•删除结点
•更新结点
•添加节点
DOM读取XML文件
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder domParser = factory.newDocumentBuilder();
Document document = domParser.parse(new File("src/cn/itcast/xml/parser/dom/car.xml"));
Element rootElement = document.getDocumentElement();
System.out.println(rootElement.getNodeName());
NodeList nodeList = rootElement.getElementsByTagName("汽车");
System.out.println("共有"+nodeList.getLength()+"辆汽车");
System.out.println("--------------------");
for(int i=0;i<nodeList.getLength();i++){
Element element = (Element) nodeList.item(i);
String band = element.getElementsByTagName("车牌").item(0).getTextContent();
String place = element.getElementsByTagName("产地").item(0).getTextContent();
String price = element.getElementsByTagName("单价").item(0).getTextContent();
String time = element.getElementsByTagName("车牌").item(0).getAttributes().getNamedItem("出产时间").getTextContent();
System.out.println("车牌:" + band);
System.out.println("产地:" + place);
System.out.println("单价:" + price);
System.out.println("出产时间:" + time);
System.out.println("--------------------");
}
DOM更新XML文件
@Test
public void testUpdate() throws Exception {
Document document = getDocument();
Element element = (Element) document.getElementsByTagName("汽车").item(1);
element.getElementsByTagName("单价").item(0).setTextContent("30万");
write2xml(document);
}
@Test
public void testDelete() throws Exception {
Document document = getDocument();
Element element = (Element) document.getElementsByTagName("汽车").item(2);
element.getParentNode().removeChild(element);
write2xml(document);
}
@Test
public void testCreate() throws Exception {
Document document = getDocument();
Element rootElement = document.getDocumentElement();
Element element = document.createElement("汽车");
Text text = document.createTextNode("我的汽车");
element.appendChild(text);
rootElement.appendChild(element);
write2xml(document);
}
private void write2xml(Document document) throws Exception {
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.transform(new DOMSource(document),new StreamResult(new File("src/cn/itcast/xml/parser/dom/car.xml")));
}
private Document getDocument() throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder domParser = factory.newDocumentBuilder();
Document document = domParser.parse(new File("src/cn/itcast/xml/parser/dom/car.xml"));
return document;
}
DOM写入XML文档
javax.xml.transform包中的Transformer类用于把代表XML文件的Document对象转换为某种格式后进行输出,利用这个对象,可以把Document对象又重新写入到一个XML文件中。
Transformer类通过transform方法完成转换操作,该方法接收一个源和一个目的地。我们可以通过:
•javax.xml.transform.dom.DOMSource类来关联要转换的document对象,
•用javax.xml.transform.stream.StreamResult 对象来表示数据的目的地。
Transformer对象通过TransformerFactory获得。
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(new File("src/cn/itcast/xml/car.xml"));
transformer.transform(source,result);
DOM类和SAX类的区别
DOM
•很方便对文档进行遍历
•对文档curd也特别方便
•ml文档比较大的时候,dom解析占用的内存也会比较大,浪费系统资源。所以dom解析这种方式不适合解析大的xml文档。
SAX
•解析文件速度快,占用资源(内存)少。
•sax解析只适合读取文档数据,不适合对文档进行增删改。