您的位置:首页 > 编程语言 > Java开发

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

2018-01-09 21:54 447 查看
  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>
fcee

</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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: