java知识点——xml补充
- 2020 年 3 月 18 日
- 筆記
1. XML解析
1.1 XML解析思路
DOM解析 Document Object Model 文件对象模型 把XML整个文件看做一个Document对象,每一个节点看做一个Element,节点中有Attribute,或者当前节点中存在Text文本内容。 DOM是将整个XML文件读取到计算机内存中,可以进行CRUD操作。 缺点: 占用了大量内存空间 适用的环境: 服务器对于XML文件的解析过程。 SAX解析 逐行读取,给予一定的事件操作。 读取一行内容,释放上一行内容,可以有效的节约内存空间 缺点: 不能对XML文件,进行增删改 适用的环境: 手机读取解析XML文件时采用的方式。
1.2 DOM图例

1.3 XML文件解析工具
1. JAXP: SUN提供的一个基本的解析器,支持DOM和SAX两种解析方式,但是操作很繁琐,不便于程序员开发。 2. Dom4j: DOM For Java 一款非常优秀的解析器 Spring,SpringMVC... 框架中集成的XML解析器 3. Jsoup: 基于Java完成的对于HTML解析的工具,因为HTML和XML文件都是标记语言。 给Jsoup一个URL,页面地址. Java的小爬虫,API很多很方便 4. PULL: Android手机上集成的XML解析工具,SAX方式解析
1.4 Dom4j使用入门
1. 导包 目前使用的是第三方工具,不是原生的JDK 导入第三方Jar包 2. 设置IDEA 3. Dom4j涉及到的方法 SAXReader(); 解析XML文件使用的核心类 read() --> XML文件Document对象 Document document = new SAXReader().read(new File("./xml/User.xml")); Document对象中可以使用方法 Element getRootElement(); 获取当前XML文件的根节点对象 Element对象中可以使用方法 List elements(); 当前节点下的所有子节点 List elements(String name); 当前节点下所有指定名字的子节点 Element element(); 获取当前节点下的第一个子节点 Element element(String name); 获取当前节点下指定名字的第一个子节点 Attribute getAttribute(String name); 根据属性名获取对应的属性对象Attribute Attribute节点中可以使用String getValue()来获取对应的节点数据 String getName(); 获取当前节点的名字 String getText(); 获取当前节点对应的文本数据
package com.qfedu.d_xmlparse; import jdk.nashorn.internal.ir.CallNode; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import java.io.File; import java.util.List; /** * @description Dom4j方法演示 * @author Anonymous * @data 2020/3/6 15:07 */ public class Demo1 { public static void main(String[] args) throws DocumentException { // 当前XML文件的Document对象 Document document = new SAXReader().read(new File("./xml/User.xml")); // 获取根节点 Root Element Element rootElement = document.getRootElement(); // 获取Root Element下子节点 List<Element> elements = rootElement.elements(); // 可以获取当前节点下的所有子节点 // System.out.println(elements); Element teacher = rootElement.element("teacher"); // 获取属性节点指定属性值 System.out.println(teacher.attribute("id").getValue()); List<Element> elements1 = teacher.elements(); for (Element element : elements1) { // 获取节点的名字 System.out.println(element.getName() + ":" + element.getText()); } } }
3.5 Dom4j Xpath解析读取XML文件
package com.qfedu.d_xmlparse; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.Node; import org.dom4j.io.SAXReader; import java.io.File; import java.util.List; /** * @description Xpath语法解析 XML文件 * @author Anonymous * @date 2020/3/6 15:55 */ public class Demo2 { public static void main(String[] args) throws DocumentException { // 当前XML文件的Document对象 Document document = new SAXReader().read(new File("./xml/User.xml")); // 获取根节点 Root Element Element rootElement = document.getRootElement(); // 无视目录结构,无视当前解析状态,直接获取所有的user节点 List list = rootElement.selectNodes("//user"); for (Object o : list) { Element element = (Element) o; int id = Integer.parseInt(element.attributeValue("id")); String name = element.element("name").getText(); int age = Integer.parseInt(element.element("age").getText()); String gender = element.element("gender").getText(); System.out.println("User[id=" + id + ", name=" + name + ", age=" + age + ", gender=" + gender + "]"); } System.out.println("--------------------------------------"); System.out.println(); // //user[index] 不考虑路径关系,获取当前XML文件中指定下标的user节点 Node node = rootElement.selectSingleNode("//user[1]"); System.out.println(node); System.out.println("--------------------------------------"); System.out.println(); // //user[@id=9] 不考虑路径关系,获取当前XML文件中指定属性为id,值为9的user节点 // @之后是属性 @id 这里需要匹配的是属性 Node node1 = rootElement.selectSingleNode("//user[@id=9]"); System.out.println(node1); System.out.println("--------------------------------------"); System.out.println(); // //user[gender='male'] 不考虑路径关系,获取当前XML文件中指定子节点为gender,对应子节点文本数据为male // 的user所有节点 List list1 = rootElement.selectNodes("//user[gender='male']"); for (Object o : list1) { System.out.println(o); } System.out.println("--------------------------------------"); System.out.println(); List list2 = rootElement.selectNodes("//user[age<20]"); for (Object o : list2) { System.out.println(o); } } } package com.qfedu.d_xmlparse; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.Node; import org.dom4j.io.SAXReader; import java.io.File; import java.util.List; /** * @description Xpath语法解析 XML文件 * @author Anonymous * @date 2020/3/6 15:55 */ public class Demo3 { public static void main(String[] args) throws DocumentException { // 当前XML文件的Document对象 Document document = new SAXReader().read(new File("./xml/User.xml")); // 获取根节点 Root Element Element rootElement = document.getRootElement(); System.out.println("--------------------------------------"); System.out.println(); // //user[last()] 这里是不考虑路径关系,获取最后一个user节点 Node node = rootElement.selectSingleNode("//user[last()]"); System.out.println(node); System.out.println("--------------------------------------"); System.out.println(); // //user[last()] 这里是不考虑路径关系,获取前两个User节点 List list = rootElement.selectNodes("//user[position() < 3]"); for (Object o : list) { System.out.println(o); } System.out.println("--------------------------------------"); System.out.println(); // //name | // age 无视路径关系,获取所有的name节点和age节点 List list1 = rootElement.selectNodes("//name | // age"); for (Object o : list1) { Element element = (Element) o; System.out.println(element.getText()); } } }
2. XML文件保存
流程: 1. 创建Document对象 2. 通过Document对象来添加元素 addElment(); addAttribute();
package com.qfedu.e_xmlwrite; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; import java.io.FileWriter; import java.io.IOException; /** * @description: 创建XML文件 * @author: Anonymous * @time: 2020/3/6 16:29 * * <students> * <student id="qf1"> * <name>骚磊</name> * <age>fdasfdsaf</age> * <sex>male</sex> * </student> * <student id="qf2"> * <name>骚磊</name> * <age>16</age> * <sex>male</sex> * </student> * </students> */ public class Demo1 { public static void main(String[] args) throws IOException { // 1. 创建了一个XML文件对应的Document对象 Document document = DocumentHelper.createDocument(); // 2. 放入到XML文件对应的Document对象中 Element root = document.addElement("students"); // 3. 在根节点之下添加了一个student节点,同时设置了属性 Element element = root.addElement("student").addAttribute("id", "qf1"); // 根节点下添加了对应的子节点,以及对应的文本 element.addElement("name").addText("骚磊"); element.addElement("age").addText("16"); element.addElement("sex").addText("male"); // 字符输出流 FileWriter fileWriter = new FileWriter("./xml/student.xml"); document.write(fileWriter); // 4. 关闭资源 fileWriter.close(); } } 5. 反射+XML文件保存读取操作 package f_xmlsave; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.io.SAXReader; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; /** * @description: * @author: Anonymous * @time: 2020/3/6 16:46 */ public class MainProject { public static void main(String[] args) throws IllegalAccessException, DocumentException, NoSuchMethodException, InvocationTargetException, IOException { ArrayList<Student> list = new ArrayList<>(); readDataFromXML(list); for (Student student : list) { System.out.println(student); } } public static void saveDateToXML(ArrayList<Student> list) throws IllegalAccessException, IOException { // 创建XML文件对应Document对象 Document document = DocumentHelper.createDocument(); // 明确根节点 Element root = document.addElement("students"); // 获取所有的成员变量Field对象 Field[] declaredFields = Student.class.getDeclaredFields(); // 循环遍历Student ArrayList集合 for (Student student : list) { // 每一个Student对象都要对应一个Student节点 Element element = root.addElement("student"); // 遍历所有的Field成员变量 for (Field declaredField : declaredFields) { declaredField.setAccessible(true); // id存储到Student节点中的属性中 if ("id".equals(declaredField.getName())) { // 所有的数据都是在String类型处理 element.addAttribute("id", declaredField.get(student) + ""); } else { // declaredField.getName() 成员变量名字 declaredField.get(student) 对应数据 element.addElement(declaredField.getName()).addText(declaredField.get(student) + ""); } } } // 字符流对象+Document对象的write方法写入XML信息到文件中 FileWriter fileWriter = new FileWriter("./xml/student.xml"); document.write(fileWriter); fileWriter.close(); } public static void readDataFromXML(ArrayList<Student> list) throws DocumentException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { Document document = new SAXReader().read(new File("./xml/student.xml")); // 找出当前XML文件中的所有student节点 List list1 = document.selectNodes("//student"); // 得到当前Student类内的所有成员变量对象,注意使用暴力反射 Field[] declaredFields = Student.class.getDeclaredFields(); /* String字符串问题 name String getText gender String getText id Integer Attribute ==> Integer age Integer getText ==> Integer */ // 遍历所有的Student节点 for (Object o : list1) { // Student节点对象 Element element = (Element) o; Student student = new Student(); // 成员变量Field数组遍历 for (Field declaredField : declaredFields) { // 给予暴力反射操作成员变量权限 declaredField.setAccessible(true); // 获取当前成员变量的数据类型 Class<?> type = declaredField.getType(); // 如果数据类型是String类型 if (type.equals(String.class)) { // String declaredField.set(student, element.element(declaredField.getName()).getText()); } else if (type.equals(Integer.class)) { // Integer类型 // 获取Integer类型中的valueOf方法 Method valueOf = type.getMethod("valueOf", String.class); if ("id".equals(declaredField.getName())) { /* id是在student节点属性中,从属性中获取对应是数据,使用valueOf方法转换成对应的Integer类型 */ declaredField.set(student, valueOf.invoke(student, element.attributeValue("id"))); } else { /* 非ID数据,从Student指定名字的子节点下获取,指定名字和成员变量名字一直,同样需要转换一下 */ declaredField.set(student,valueOf.invoke(student, element.element(declaredField.getName()).getText())); } } } list.add(student); } } }