java详解 --- Dom4j解析XML文档

  dom4j是一个简单的开源库 , 用于处理XML , XPath和XSLT , 它基于Java平台 , 使用Java的集合框架 , 全面集成了DOM , SAX和JAXP , 今天主要说说dom4j解析xml文件.

首先创建一个xml文件:取名为School.xml
<?xml version="1.0" encoding="utf-8"?>
<School value="老师+学生">
    <!--
        CDATA语法:该语法规定语法内的文字为XML语法不解析的内容
        CDATA语法内的内容为纯文本
     -->
     <![CDATA[
        <省重点>民办高级小学
    ]]>
    学校
    <Teachers name="老师">
        <Teacher id="001">
            <name>T1</name>
            <gender></gender>
            <subject>艺术</subject>
            <salary>800/天</salary>
        </Teacher>
        <Teacher id="002">
            <name>T2</name>
            <gender></gender>
            <subject>美术</subject>
            <salary>500/天</salary>
        </Teacher>
        <Teacher id="003">
            <name>T3</name>
            <gender></gender>
            <subject>生物</subject>
            <salary>1000/天</salary>
        </Teacher>
    </Teachers>

    <Students name="学生">
        <Student id="01">
            <name>S1</name>
            <gender></gender>
            <class>三班</class>
        </Student>
        <Student id="02">
            <name>S2</name>
            <gender></gender>
            <class>五班</class>
        </Student>
        <Student id="03">
            <name>S3</name>
            <gender></gender>
            <class>一班</class>
        </Student>
    </Students>
</School>

一.XML文档的解析

1.为什么要解析XML文档?
原因:xml文档是用来存放数据的 , 这些数据需要被程序传递 并 使用 , 但是xml文档的语法和使用它的语言的语法规则不同 , 所以需要根据使用它语法的语法规则 和 xml文档规则将xml文档存储的数据转换成想使用它语言能使用的数据 , 这个过程就叫做xml文档解析

2.应用
因为xml文档在各语言基础上定义一致 , 并且解析逻辑一致 , 所以用于各语言之间的数据转换

3.xml常用的解析规则
1).DOM - document
DOM是面向文档结构树的对象模型解析

优点:可以清晰的展示节点的层次关系 和 连带关系 , 具有强大的节点操作功能

缺点:该方式会将整个文档解析的DOM树整体存放在内存中 , 不利于大型文档的操作

2).SAX - simple api for xml
SAX是面向文档接口的逻辑模型解析

优点:具有快速处理xml文档的能力 , 节约内存空间(根据需求进行必要的局部解析 且 前后解析具有很大的灵活性)

缺点:无法标注节点之间的层次关系 , 节点功能操作单一化

3).Dom4j
整合了各种语法解析的优点 具有灵活的DOM文档树的内存印象

二.Dom4j解析文档

1.Dom4j解析文档
1).步骤
① 通过SAXReader()空控制器方法生成操作XML文档的输出流
② 通过读取操作 与文件 或 流 建立起直接关系

public static void main(String[] args) throws Exception {
        // Dom4j解析文档
        SAXReader reader = new SAXReader();

        String path = SD.getPath(SD.d_s , "lesson" , "xml");
        File file = new File(path, "School.xml");

        Document doc = reader.read(file);

        System.out.println(doc);
    }

2).Dom4j文档解析的数据操作

    // Dom4j文档解析的操作
    SAXReader reader = new SAXReader();

    String path = SD.getPath(SD.d_s , "lesson" , "xml");
    File file = new File(path , "School.xml");

    Document doc = reader.read(file);

    // 1. 数据相关操作

    // ① 获取根节点
    Element root = doc.getRootElement();

    // ② 获取节点的内容
    // 保留数据中的空格文本
    String tTxt = root.getText();
    // 将数据中的空格做最简处理
    String tTxtr = root.getTextTrim(); 
    System.out.println("② " + tTxt);
    System.out.println("② " + tTxtr);

    // ③ 获取节点属性
    // 获取属性的个数
    System.out.println("③.属性个数为: " + root.attributeCount());
    // 根据索引获取对应节点属性
    Attribute attr = root.attribute(0);
    // 根据key值获取对应属性
    // Attribute attr = root.attribute("value");
    System.out.println("③ " + attr);

    // ④ 获取节点属性值
    String key = attr.getName();
    String value = attr.getValue();
    System.out.println("④ " + key + ": " + value);

    // 2.节点相关操作
    // 获取子节点
    List<Element> list = root.elements();
    for (Element element : list) {
        // ⑤ 节点名
        System.out.println("⑤ " + element.getName());
    }

    // ⑥ 获取指定节点
    Element Teacher = root.element("Teachers");
    System.out.println("⑥ " + Teacher.getName());

    // ⑦ 获取父节点
    Element parent = Teacher.getParent();
    // 判断是否与根节点相同
    System.out.println("⑦ " + (parent == root));

三.利用Dom4j将xml解析为集合形式和对象形式

1.利用Dom4j将xml解析为集合形式

// 将xml文档解析成 集合 形式
        String path = SD.getPath(SD.d_s , "lesson" , "xml");
        File file = new File(path , "School.xml");

        SAXReader reader = new SAXReader();
        Document document = reader.read(file);

        // 获取School节点
        Element root = document.getRootElement();

        // Students / Teachers 的节点
        Element teas = root.element("Teachers");
        Element stus = root.element("Students");

        // 获取Students / Teachers的子节点们 
        List<Element> ts = teas.elements();
        List<Element> ss = stus.elements();

        // 获取存放老师们的Collection
        Collection<Map<String, String>> tColl = new ArrayList<>();
        // 获取老师的具体数据
        // t --> Teacher * 3
        for (Element t : ts) {
            // 获取存放老师信息的Map集合
            Map<String, String> tMap = new HashMap<>();
            // id是特殊属性 需特殊操作
            tMap.put("id", t.attributeValue("id"));
            // 遍历Teacher所有子节点 遍历过程中循环操作节点 及 节点数据
            for (Object ele : t.elements()) {
                // e -> name / gender / subject / salary
                Element e = (Element)ele;
                // key:代表标签名 value:代表标签值
                tMap.put(e.getName(), e.getText());
            }
            tColl.add(tMap);
        }

        // 获取存放学生的Collection
        Collection<Map<String,String>> sColl = new ArrayList<>();
        // 获取学生的具体数据
        // s -> Student * 4
        for (Element s : ss) {
            // 获取存放学生的map
            Map<String, String> sMap = new HashMap<>();
            // Num是特殊属性 需特殊操作
            sMap.put("Num", s.attributeValue("Num"));
            for (Object ele : s.elements()) {
                Element e = (Element)ele;
                sMap.put(e.getName(), e.getText());
            }
            sColl.add(sMap);
        }

        // 获取学校School总集合
        Collection<Map<String, Collection<Map<String, String>>>> S = new ArrayList<>();

        // 获取老师们 和 学生们的map总集合
        Map<String, Collection<Map<String, String>>> tsMap = new HashMap<>();
        Map<String, Collection<Map<String, String>>> ssMap = new HashMap<>();
        tsMap.put("Teachers", tColl);
        ssMap.put("Students", sColl);
        S.add(tsMap);
        S.add(ssMap);
        System.out.println(S);

2.利用Dom4j将xml解析为对象形式
既然是对象形式,首先创建三个类:
School类 Teacher类 Student类

// 学校类
class School{
    private String msg;
    private Collection<Teacher> teachers;
    private Collection<Student> students;

    public String Msg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }

    // 问题一:在getter方法期间 应该将teachers / students 处理完毕
    // 解决:在构造School的类对象时 处理teachers / students
    public School() {
        this.teachers = new ArrayList<>();
        this.students = new ArrayList<>();
    }

    // 问题二:如何做到对外接口为添加单一 老师 / 学生
    // 按照功能性设计setter方法
    public void setTeacher(Teacher t) {
        this.teachers.add(t);
    }
    public void setStudents(Student s) {
        this.students.add(s);
    }

    // 问题三:如何设计getter方法
    /*
     * 解决:数据解析的最终目的 是使用解析到的数据
     * 因此如何最方便直接的得到 就如何设计getter方法
     */

    // 老师的getter方法
    public Collection<Teacher> Teacher(){
        return teachers;
    }
    public Teacher getTeacher(int index) {
        if (index >= teachers.size()) {
            return null;
        }
        return ((ArrayList<Teacher>)teachers).get(index);
    }

    // 学生的getter方法
    public Collection<Student> students(){
        return students;
    }
    public Student getStudent(int index) {
        if (index >= students.size()) {
            return null;
        }
        return ((ArrayList<Student>) students).get(index);
    }

    // 重写toString方法
    @Override
    public String toString() {
        return "School [msg=" + msg + ", teachers=" + teachers + ", students=" + students + "]";
    }
}

// 老师类
class Teacher{
    private String id;
    private String name;
    private String gender;
    private String subject;
    private String salary;

    // set / get 方法
    // setName / getName | Name都可以
    public String ID() {
        return id;
    }
    public void setID(String iD) {
        this.id = iD;
    }
    public String Name() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String Gender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public String Subject() {
        return subject;
    }
    public void setSubject(String subject) {
        this.subject = subject;
    }
    public String Salary() {
        return salary;
    }
    public void setSalary(String salary) {
        this.salary = salary;
    }

    // 重写toString方法
    @Override
    public String toString() {
        return "Teacher [ID=" + id + ", name=" + name + ", gender=" + gender + ", subject=" + subject + ", salary="
                + salary + "]";
    }
}

// 学生类
class Student{
    private String num;
    private String name;
    private String gender;
    private String clazz;

    // set / get 方法
    public String Num() {
        return num;
    }
    public void setNum(String num) {
        this.num = num;
    }
    public String Name() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String Gender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public String Clazz() {
        return clazz;
    }
    public void setClazz(String clazz) {
        this.clazz = clazz;
    }

    // 重写toString方法
    @Override
    public String toString() {
        return "Student [Num=" + num + ", name=" + name + ", gender=" + gender + ", clazz=" + clazz + "]";
    }
}

main方法:

    // 使用解析后的结果
private static void useResult(School school) {
    System.out.println(school);

    // 获取所有学生的信息
    Collection<Student> stus = school.Students();
    System.out.println(stus);

    // 获取第三个学生
    Student stu = school.getStudent(2);
    System.out.println(stu);

    // 获取第一个学生的班级
    String clazz = school.getStudent(0).Clazz();
    System.out.println(clazz);
}

public static void main(String[] args) throws Exception{
    // 将xml文档解析成 单一对象 形式
    // 最终结果
    School school = new School();

    // 解析数据
    SAXReader reader = new SAXReader();

    String path = SD.getPath(SD.d_s , "lesson" , "xml");
    File file = new File(path, "School.xml");

    Document document = reader.read(file);

    // 获取根节点
    Element root = document.getRootElement();

    // root.elements() -- School所有的子节点
    for (Object object : root.elements()) {
        // (Element)object --> Teachers / Students
        analyseObject((Element)object , school);
    }
    school.setMsg(root.getTextTrim());
    // 打印结果
    System.out.println(school);
}
// 参数element -- Teachers / Students
private static void analyseObject(Element element , School school) {
    // element.elements() --> Teachers / Students的所有子节点
    for (Object obj : element.elements()) {
        // ele --> Teacher节点 * 3 / Student节点 *4
        Element ele = (Element)obj;
        // 如果ele为Teacher -- analyseTeacher
        // 如果ele为Student -- analyseStudent
        if (ele.getName().equals("Teacher")) {
            Teacher t = analyseTeacher(ele);
            school.setTeacher(t);
        }
        if (ele.getName().equals("Student")) {
            school.setStudents(analyseStudent(ele));
        }
    }
}

//参数ele -- Teacher节点
private static Teacher analyseTeacher(Element ele) {
    Teacher t = new Teacher();
    // id为特殊节点 特殊处理
    t.setID(ele.attributeValue("id"));
    // name / gender / subject / salary
    t.setName(ele.element("name").getText());
    t.setGender(ele.element("gender").getText());
    t.setSubject(ele.element("subject").getText());
    t.setSalary(ele.element("salary").getText());
    return t;
}

// 参数ele -- Student节点
private static Student analyseStudent(Element ele) {
    Student s = new Student();
    // Num 通过属性进行设置
    s.setNum(ele.attributeValue("num"));
    // name / gender / class -- 通过子标签进行设置
    s.setName(ele.element("name").getText());
    s.setGender(ele.element("gender").getText());
    s.setClazz(ele.element("class").getText());
    return s;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值