随笔都是学习笔记
随笔仅供参考,为避免笔记中可能出现的错误误导他人,请勿转载。

简介:

dom4j的解析是从上到下的。

dom4j不是javase的一部分,所以需要导入dom4j的jar包。

首先是进入dom4j下载jar包:

下载完成后在eclipse新建一个lib文件夹:

 

 

 

将下载的jar包复制到lib文件夹中:

 

 

 复制后右击lib文件夹,选择构建路径(builder-panth),然后点配置构建路径:

 

 

 

 

 然后按照步骤(必须导入类路径):

 

 

 

 

 

 然后再跟着步骤:

 

 

 最后应用并关闭就能看到一个引用的库里面有下载的jar包:

 

 

 dom4j的应用:

 首先查看org.dom4j.io下的SAXReader类:

public class SAXReader
extends Object

在SAXReader类中有一个方法

从给定的文件中读取一个文档:public Document read(File file) throws DocumentException

返回一个新创建的Document实例对象;

public interface Document
extends Branch

public interface Branch
extends Node

可以发现Document是Node接口的子接口,所以Document实例对象可以使用父接口Node的方法,

在Document中有一个方法:

返回根元素:public Element getRootElement();

在Node中有方法:

返回父节点(不存在则返回空):
    public Element getParent();
判断此节点是否支持父节点:
    public boolean supportsParent();
设置父节点(如果不支持父节点则无操作):
    public void setParent(Element parent);
返回节点的文本:
    public String getText();
判断此节点是否为只读:
    public boolean isReadOnly();
设置文本内容(节点为可写,isReadOnly为false):
    public void setText(String text);

 

案例:

用dom4j实现获取xml中节点的文本信息:

新建person.xml文档:

<?xml version="1.0" encoding="UTF-8"?>
<person>
    <p1>
        <name>zs</name>
        <age>11</age>
    </p1>
    <p1>
        <name>ls</name>
        <age>11</age>
    </p1>
</person>

获取person.xml下<name>节点的文本内容:

package dom4jDemo1;

import java.io.File;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class Dom4jParseXml {
    public static void main(String[] args) throws Exception{
        selectName();
    }
    public static void selectName() throws Exception {
        // 创建解析器
        SAXReader reader = new SAXReader();
        // 通过read()方法读取xml
        Document doc = reader.read("src" + File.separator + "dom4jDemo1" + File.separator + "dom4j1_1.xml");
        // 得到根节点
        Element rootElement = doc.getRootElement();
        // 获取p1节点
        List<Element> lists = rootElement.elements("p1");
        for (Element element : lists) {
       // Element就是p1,有两个p1
// 获取name节点 Element name = element.element("name"); // 获取name节点的文本内容 String text = name.getText(); System.out.println(text); } } }

输出结果:

通过集合的get(int index)获取索引位置的标签,然后获取标签文本内容:

package dom4jDemo1;

import java.io.File;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class Dom4jParseXml {
    public static void main(String[] args) throws Exception{
        selectName();
    }
    public static void selectName() throws Exception {
        // 创建解析器
        SAXReader reader = new SAXReader();
        // 通过read()方法读取xml
        Document doc = reader.read("src" + File.separator + "dom4jDemo1" + File.separator + "dom4j1_1.xml");
        // 得到根节点
        Element rootElement = doc.getRootElement();
        // 获取p1节点
        List<Element> lists = rootElement.elements("p1");
        // 通过List中的get()方法获取对应索引位置的元素        
        System.out.println(lists.get(0).element("age").getText());
    }
}

输出结果:

 

 

 为了体现dom4j从上到下解析的过程,新建一个方法进行重复获取:

 

 

public static void selectNameF() throws Exception {
        // 创建解析器
        SAXReader reader = new SAXReader();
        // 通过read()方法读取xml
        Document doc = reader.read("src" + File.separator + "dom4jDemo1" + File.separator + "dom4j1_1.xml");
        // 得到根节点
        Element rootElement = doc.getRootElement();
        // 获取p1
        Element p1 = rootElement.element("p1");
        // 获取p1下的name
        Element name = p1.element("name");
        // 获取name文本
        String text1 = name.getText();
        // 获取p1
        Element p1_2 = rootElement.element("p1");
        // 获取p1下的name
        Element name2 = p1_2.element("name");
        // 获取name文本
        String text2 = name2.getText();
        System.out.println(text1);
        System.out.println(text2);
    }

 

 

输出结果:

可以发现,在进行重复获取<p1>的时候并不是第一个<p1>标签进行了两次获取,而是获取一次第一个<p1>标签之后,又向下获取第二个<p1>标签,所以可以得到第一个<name>标签的文本内容和第二个<name>标签的文本内容。

 

 

 使用dom4j进行添加操作:

有一个写入流XMLWriter:

java.lang.Object
  extended byorg.xml.sax.helpers.XMLFilterImpl
      extended byorg.dom4j.io.XMLWriter
public class XMLWriter
extends XMLFilterImpl
implements LexicalHandler

构造方法:

public XMLWriter(OutputStream out,OutputFormat format) throws UnsupportedEncodingException

其中有一个写入的操作方法:

public void write(Document doc) throws IOException

传入的是Document类型参数,一般这个参数都是在回写xml操作之前进行了修改的参数。

/**
     * 在第一个p1标签后添加一个sex标签并设置文本内容为nv
     * @throws Exception
     */
    public static void addSex() throws Exception{
        // 创建解析器
        SAXReader reader = new SAXReader();
        // 解析xml
        Document doc = reader.read("src" + File.separator + "dom4jDemo1" + File.separator + "dom4j1_1.xml");
        // 获取根节点
        Element rootElement = doc.getRootElement();
        // 获取第一个p1 
        Element p1_1 = rootElement.element("p1");
        // 添加新节点sex
        Element sex = p1_1.addElement("sex");
        // 设置sex节点文本
        sex.setText("nv");
        
        // 回写xml
        // 格式化文本,有缩进的效果
        OutputFormat format = OutputFormat.createPrettyPrint();
        // XML输出流
        XMLWriter write = new XMLWriter(new FileOutputStream("src" + File.separator + "dom4jDemo1" + File.separator + "dom4j1_1.xml"),format);
        // 写入读取的已经修改后的xml文档,此时的doc是已经修改后的xml数据
        write.write(doc);
        // 关闭流
        write.close();
        System.out.println("ok");
    }

 添加成功:

<?xml version="1.0" encoding="UTF-8"?>

<person> 
  <p1> 
    <name>zs</name>  
    <age>11</age>
    <sex>nv</sex>
  </p1>  
  <p1> 
    <name>ls</name>  
    <age>11</age> 
  </p1> 
</person>

如果使用另一个OutputFormat的static方法:OutputFormat.createCompactFormat();

        OutputFormat format = OutputFormat.createCompactFormat();

会发现xml内容会被压缩为一行:

 

在指定位置添加新元素:

这里会使用一个DocumentHelper类:

java.lang.Object
  extended byorg.dom4j.DocumentHelper
public final class DocumentHelper
extends Object

可以发现这个类是final修饰的,所以其中的方法都是static方法可以直接用 类名. 的形式进行调用,那么就会使用到其中的一个方法:

public static Element createElement(String name)

使用 DocumentHelper.createElement("school") 可以直接创建一个名为"school"的新标签,然后使用List集合的add(int index,Element ele)方法将新标签添加进去,添加时确定添加位置也是在add()方法中。

/**
     * 在age标签前面添加school标签
     * @throws Exception
     */
    public static void addSchool() throws Exception{
        // 创建解析器
        SAXReader reader = new SAXReader();
        // 解析xml
        Document doc = reader.read("src" + File.separator + "dom4jDemo1" + File.separator + "dom4j1_1.xml");
        // 获取根元素
        Element rootElement = doc.getRootElement();
        // 获取第一个p1
        Element p1_1 = rootElement.element("p1");
        // 获取第一个p1下的所有标签元素
        List<Element> lists = p1_1.elements();
        // 创建新元素
        Element school = DocumentHelper.createElement("school");
        // 添加元素,第一个参数是索引,第二个参数是新元素,表示在索引位置添加新元素
        lists.add(1, school);
        // 设置文本
        school.setText("hope school");
        
        // 回写xml
        // 格式化缩进
        OutputFormat format = OutputFormat.createPrettyPrint();
        // 写入流
        XMLWriter writer = new XMLWriter(new FileOutputStream("src" + File.separator + "dom4jDemo1" + File.separator + "dom4j1_1.xml"),format);
        // 写入操作
        writer.write(doc);
        // 关闭流
        writer.close();
        // 提示完成
        System.out.println("its ok!");        
    }

添加后的xml:

<?xml version="1.0" encoding="UTF-8"?>

<person> 
  <p1> 
    <name>zs</name>  
    <school>hope school</school>
    <age>11</age>
    <sex>nv</sex> 
  </p1>  
  <p1> 
    <name>ls</name>  
    <age>11</age> 
  </p1> 
</person>

 

将重复的操作封装为方法:

package cn.dom4jUtile.lm;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.UnsupportedEncodingException;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public final class Dom4jUtils {
    /**
     * 将xml的回写操作封装为一个方法
     * @param xmlPath:xml的路径
     * @param doc:回写操作前修改数据后的Document对象
     */
    public static void ReWriteXml(String xmlPath,Document doc) {
        try {
        //缩进文本
        OutputFormat format = OutputFormat.createPrettyPrint();
        // 创建写入流
            XMLWriter Writer = new XMLWriter(new FileOutputStream(xmlPath),format);
            Writer.write(doc);
            Writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        } 
    }
    /**
     * 将创建解析器和解析xml的步骤封装为一个方法
     * @param path    xml文件的路劲
     * @return
     */
    public static Document getDocument(String path) {
        try {
            // 创建解析器
            SAXReader reader = new SAXReader();
            // 解析xml得到Document
            Document doc = reader.read(path);
            return doc; 
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
}

 可以发现在上面的代码仍然有重复的地方可以改进,那就是路径,那么就可以设置一个路径常量,这样就可以在对路径进行修改的时候达到改一而改全部的目的:

package cn.dom4jUtile.lm;
import java.io.File;
import java.io.FileOutputStream;
import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public final class Dom4jUtils {
    public static final String PATH="src" + File.separator + "dom4jDemo1" + File.separator + "dom4j1_1.xml";
    
    /**
     * 将xml的回写操作封装为一个方法
     * @param xmlPath:xml的路径
     * @param doc:回写操作前修改数据后的Document对象
     */
    public static void ReWriteXml(Document doc) {
        try {
        //缩进文本
        OutputFormat format = OutputFormat.createPrettyPrint();
        // 创建写入流
            XMLWriter Writer = new XMLWriter(new FileOutputStream(PATH),format);
            Writer.write(doc);
            Writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        } 
        
        
    }
    /**
     * 将创建解析器和解析xml的步骤封装为一个方法
     * @param path    xml文件的路劲
     * @return
     */
    public static Document getDocument() {
        try {
            // 创建解析器
            SAXReader reader = new SAXReader();
            // 解析xml得到Document
            Document doc = reader.read(PATH);
            return doc; 
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
}

这样在修改xml文档路径的时候就可以直接修改路径常量,就可以修改所有的路径了。

这样就大大减少了代码的重复性,降低了时间成本。

 

使用dom4j实现修改节点内容的操作:

/**
     * 创建一个方法:删除第一个p1下的school元素
     */
    public static void removeSchool() {
        // 获取解析xml后的Document对象
        Document doc = Dom4jUtils.getDocument();
        // 获取根节点
        Element rootElement = doc.getRootElement();
        // 获取第一个p1
        Element p1_1 = rootElement.element("p1");
        // 获取第一个p1下的school元素 
        Element school = p1_1.element("school");
//        // 得到父节点
//        Element parent = school.getParent();
//        // 通过父节点删除school元素
//        parent.remove(school);
        // 直接使用p1删除school
        p1_1.remove(school);
        // 回写xml
        Dom4jUtils.ReWriteXml(doc);
        
    }

删除后:

<?xml version="1.0" encoding="UTF-8"?>

<person> 
  <p1> 
    <name>zs</name>  
    <age>100</age>  
    <sex>nv</sex> 
  </p1>  
  <p1> 
    <name>ls</name>  
    <age>11</age> 
  </p1> 
</person>

 

获取元素的属性:

public Attribute attribute(int index)

获取元素属性列表中的第 index 个,例如元素有两个属性,那么元素A.attribute(0):表示获取元素A的第一个属性

public Attribute attribute(String name)

获取指定名称的属性。

        /**
     * 获取第一个p1下的name标签的属性
     */
    public static void getAttribute() {
        // 获取解析xml后的Document对象
        Document doc = Dom4jUtils.getDocument();
        // 获取根节点
        Element rootElement = doc.getRootElement();
        // 获取第一个p1
        Element p1_1 = rootElement.element("p1");
        // 获取name
        Element name = p1_1.element("name");
        // 获取name中的属性,0:索引为0,表示第一个属性
        Attribute at = name.attribute(0);
        System.out.println(at.getName() + ": " + at.getData());    
    }    

输出结果:

 

posted on 2022-03-27 11:19  时间完全不够用啊  阅读(1500)  评论(0编辑  收藏  举报