XML之dom4j解析


簡介:

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()); }  

輸出結果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM