dom4j解析器 基于dom4j的xpath技术 简单工厂设计模式 分层结构设计思想 SAX解析器 DOM编程

*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()+"	");
                System.out.print("产地:"+car.getPlace()+"	");
                System.out.print("单价:"+car.getPrice()+"	");
                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文件内容作为方法的参数传递给事件处理器。

image

阅读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解析只适合读取文档数据,不适合对文档进行增删改。

原文地址:https://www.cnblogs.com/sunhan/p/3542143.html