淺談 Java 主流開源類庫解析 XML

来源:http://www.cnblogs.com/java-class/archive/2017/05/25/6901910.html
-Advertisement-
Play Games

在大型項目編碼推進中,涉及到 XML 解析問題時,大多數程式員都不太會選用底層的解析方式直接編碼。 主要存在編碼複雜性、難擴展、難復用....,但如果你是 super 程式員或是一個人的項目,也不妨一試。 Jdom/Dom4j/Xstream... 基於底層解析方式重新組織封裝的開源類庫,簡潔明瞭的 ...


   在大型項目編碼推進中,涉及到 XML 解析問題時,大多數程式員都不太會選用底層的解析方式直接編碼。

   主要存在編碼複雜性、難擴展、難復用....,但如果你是 super 程式員或是一個人的項目,也不妨一試。

   Jdom/Dom4j/Xstream... 基於底層解析方式重新組織封裝的開源類庫,簡潔明瞭的 API,穩定高效的運行表現。

   Dom4j 基於 JAXP 解析方式,性能優異、功能強大、極易使用的優秀框架。想瞭解底層解析方式請翻看:淺談 Java XML 底層解析方式

   Jdom 你細看內部代碼,本質也是基於 JAXP 但包結構被重新組織, API 大量使用了 Collections 類,在性能上被 dm4j 壓了好幾個檔次。

   Xstream 基於 xmlpull 的 OXMapping 技術,更加傾向於將 XML 解析後映射為 Java 世界中的對象,等會在代碼中會看的很清楚。

   如果你是一名大型項目技術負責人,需求中涉及 XML 解析方面的要求,在程式員編碼開始前你需要在充分瞭解需求的前提下。

   來拿捏 XML 解析解決方案所採用的技術,請收藏這篇博客,到時將會給你一些幫助和指導。

   需要解析的還是上篇的中 demo.xml,中規中矩不複雜也不簡單,實例 demo 地址:https://git.oschina.net/LanboEx/xml-parse-demo.git

<?xml version="1.0"?>
<classGrid>
    <classGridlb>
        <class_id>320170105000009363</class_id>
        <class_number>0301</class_number>
        <adviser>018574</adviser>
        <studentGrid>
            <studentGridlb>
                <stu_id>030101</stu_id>
                <stu_name>齊天</stu_name>
                <stu_age>9</stu_age>
                <stu_birthday>2008-11-07</stu_birthday>
            </studentGridlb>
            <studentGridlb>
                <stu_id>030102</stu_id>
                <stu_name>張惠</stu_name>
                <stu_age>10</stu_age>
                <stu_birthday>2009-04-08</stu_birthday>
            </studentGridlb>
            <studentGridlb>
                <stu_id>030103</stu_id>
                <stu_name>龍五</stu_name>
                <stu_age>9</stu_age>
                <stu_birthday>2008-11-01</stu_birthday>
            </studentGridlb>
        </studentGrid>
    </classGridlb>
    <classGridlb>
        <class_id>420170105000007363</class_id>
        <class_number>0302</class_number>
        <adviser>018577</adviser>
        <studentGrid>
            <studentGridlb>
                <stu_id>030201</stu_id>
                <stu_name>馬寶</stu_name>
                <stu_age>10</stu_age>
                <stu_birthday>2009-09-02</stu_birthday>
            </studentGridlb>
        </studentGrid>
    </classGridlb>
</classGrid>
demo.xml

1. Jdom

   Jdom 基於樹處理 XML,需要將樹載入到記憶體中,所以你懂的大於記憶體的 XML 文件,Jdom 其實是拒絕的。

   Jdom 具有 SAX 的 java 規則,可以使用推模型分析 XML,所以在一定程度上解析速度可以保證。

   Jdom 沒有向下相容的限制,所以比底層 dom 簡單,但在表示文檔邏輯模型時,不能保證每個位元組真正變換。

   mvn 依賴:

        <dependency>
            <groupId>jdom</groupId>
            <artifactId>jdom</artifactId>
            <version>1.1</version>
        </dependency>

   實例 demo (將 demo.xml studentGridlbb 節點的值解析出來,組成業務實體對象) 。

        String path = Thread.currentThread().getContextClassLoader().getResource("demo.xml").getPath();

        SAXBuilder jdomsaxBuilder = new SAXBuilder(false);
        Document doc = jdomsaxBuilder.build(path);
        Element rootElement = doc.getRootElement();

        List<StudentGridlb> studentGridlbList = new ArrayList<>();
        StudentGridlb studentGridlb;
        for (Object classGridlb : rootElement.getChildren("classGridlb")) {
            Element classGridlbEle = (Element) classGridlb;

            for (Object studentGrid : classGridlbEle.getChild("studentGrid").getChildren("studentGridlb")) {
                Element studentGridEle = (Element) studentGrid;
                studentGridlb = new StudentGridlb();
                studentGridlb.setStu_id(studentGridEle.getChildTextTrim("stu_id"));
                studentGridlb.setStu_age(Integer.parseInt(studentGridEle.getChildTextTrim("stu_age")));
                studentGridlb.setStu_name(studentGridEle.getChildTextTrim("stu_name"));
                DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
                studentGridlb.setStu_birthday(format.parse(studentGridEle.getChildTextTrim("stu_birthday")));
                studentGridlbList.add(studentGridlb);
            }
        }

        XMLOutputter outputter = new XMLOutputter();
        outputter.output(doc, new FileOutputStream(path));

2. Dom4j

   Dom4j 為了支持 XPath、XML Schema、基於事件處理大文檔或流文檔。

   Dom4j 為提供構建文檔表示的選項,為可通過 Dom4j-API 和標準底層 dom-API 並行訪問功能。

   為實現上述巨集偉目標,Dom4j 使用介面和抽象基本類方法並大量使用 JDK 中 Collections 類。

   所以 Dom4j 有豐富的 API,在靈活性上面 Dom4j 更占有優勢,性能方面也無可挑剔。

   聲名在外的 Sun-JAXM,大名鼎鼎的 Hibernate 中XML 配置文件解析都使用的是 Dom4j。

   mvn 依賴:

       <!--MetaStuff dom4j-->
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
            <exclusions>
                <exclusion>
                    <groupId>xml-apis</groupId>
                    <artifactId>xml-apis</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

  剔除 xml-apis 的用意 JDK 中已經有對應的類,如不剔除在部署 weblogic 時會出現 Jar 衝突。

  實例 demo (將 demo.xml studentGridlbb 節點的值解析出來,組成業務實體對象) 。

        String path = Thread.currentThread().getContextClassLoader().getResource("demo.xml").getPath();

        SAXReader reader = new SAXReader();
        Document document = reader.read(new File(path));

        List<StudentGridlb> studentGridlbList = new ArrayList<>();
        StudentGridlb studentGridlbVo;
        for (Object classGridlb : document.getRootElement().elements("classGridlb")) {
            Element classGridlbEle = (Element) classGridlb;

            for (Object studentGridlb : classGridlbEle.element("studentGrid").elements("studentGridlb")) {
                Element studentGridlbEle = (Element) studentGridlb;

                studentGridlbVo = new StudentGridlb();
                studentGridlbVo.setStu_id(studentGridlbEle.elementTextTrim("stu_id"));
                studentGridlbVo.setStu_age(Integer.parseInt(studentGridlbEle.elementTextTrim("stu_age")));
                studentGridlbVo.setStu_name(studentGridlbEle.elementTextTrim("stu_name"));
                DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
                studentGridlbVo.setStu_birthday(format.parse(studentGridlbEle.elementTextTrim("stu_birthday")));
                studentGridlbList.add(studentGridlbVo);
            }
        }

3. Xstream

   Xstream 為基於註解不需要其它輔助類或映射文件 的OXMapping 技術,如果你用過 hibernate 或 mybatis 之類的 ORM 框架就不難理解這裡的 OXM。

   Xstream 可以將 JavaBean 序列化為 XML,或將 XML 反序列化為 JavaBean,使得XML序列化不再繁瑣。

   Xstream 也可以將 JavaBean 序列化成 Json 或反序列化,使用非常方便。

   沒有映射文件而且底層使用 xmlpull 推模型解析 XML,高性能、低記憶體占用,結合簡潔明瞭的 API,上手基本是分分鐘的事情。

   Xstream 同時也可以定製轉換類型策略並配有詳細的錯誤診斷,能讓你快速定位問題。

   使用 Xstream 時,規範和合理的業務對象命名是關鍵,下麵是針對 demo.xml 我抽象的幾個業務實體。

@XStreamAlias("classGrid")
public class ClassGrid {

    @XStreamImplicit(itemFieldName="classGridlb")
    private List<ClassGridlb> classGridlbList;

    public List<ClassGridlb> getClassGridlbList() {
        return classGridlbList;
    }

    public void setClassGridlbList(List<ClassGridlb> classGridlbList) {
        this.classGridlbList = classGridlbList;
    }
}
ClassGrid
@XStreamAlias("classGridlb")
public class ClassGridlb {
    private String class_id;
    private String class_number;
    private String adviser;

    private StudentGrid studentGrid;

    public String getClass_id() {
        return class_id;
    }

    public void setClass_id(String class_id) {
        this.class_id = class_id;
    }

    public String getClass_number() {
        return class_number;
    }

    public void setClass_number(String class_number) {
        this.class_number = class_number;
    }

    public String getAdviser() {
        return adviser;
    }

    public void setAdviser(String adviser) {
        this.adviser = adviser;
    }

    public StudentGrid getStudentGrid() {
        return studentGrid;
    }

    public void setStudentGrid(StudentGrid studentGrid) {
        this.studentGrid = studentGrid;
    }
}
ClassGridlb
@XStreamAlias("studentGrid")
public class StudentGrid {

    @XStreamImplicit(itemFieldName="studentGridlb")
    private List<StudentGridlb> studentGridlbList;

    public List<StudentGridlb> getStudentGridlbList() {
        return studentGridlbList;
    }

    public void setStudentGridlbList(List<StudentGridlb> studentGridlbList) {
        this.studentGridlbList = studentGridlbList;
    }
}
StudentGrid
@XStreamAlias("studentGridlb")
public class StudentGridlb {
    private String stu_id;
    private String stu_name;
    private Integer stu_age;

    @XStreamConverter(value=DateConverter.class)
    private Date stu_birthday;

    public String getStu_id() {
        return stu_id;
    }

    public void setStu_id(String stu_id) {
        this.stu_id = stu_id;
    }

    public String getStu_name() {
        return stu_name;
    }

    public void setStu_name(String stu_name) {
        this.stu_name = stu_name;
    }

    public Integer getStu_age() {
        return stu_age;
    }

    public void setStu_age(Integer stu_age) {
        this.stu_age = stu_age;
    }

    public Date getStu_birthday() {
        return stu_birthday;
    }

    public void setStu_birthday(Date stu_birthday) {
        this.stu_birthday = stu_birthday;
    }

    @Override
    public String toString() {
        return "StudentGridlb{" + "stu_id='" + stu_id + '\'' + ", stu_name='" + stu_name + '\'' + ", stu_age=" + stu_age + ", stu_birthday=" + stu_birthday + '}';
    }
}
StudentGridlb

   抽象好 XML 業務實體之後,接下來就很簡單了,只需要三行代碼。

        Xstream Xstream = new Xstream(new DomDriver());
        Xstream.processAnnotations(ClassGrid.class);
        ClassGrid classGrid = (ClassGrid) Xstream.fromXML(new File(Thread.currentThread().getContextClassLoader().getResource("demo.xml").getPath()));

4. 小結

   如果你看到過我上篇寫過的底層解析方式和這篇的開源類庫對比下,封裝優秀類庫,代碼的編寫量會小很多,而且簡化的 API 使用起來很順手。

   Dom4j/Jdom 都支持對 XML 文檔的增刪改查動作,畢竟是已樹模型載入到記憶體中進行的操作。

   Xstream 專註於 XML 和業務對象之間的序列化和反序列化,刪除和修改原 XML 文檔實踐起來相當困難。

   我個人的建議,在項目中同時引入 Dom4j 和 Xstream,在 XMl 複雜情況下,可以考慮使用 Dom4j 獲取出感興趣的部分。

   然後抽象出合適的業務實體,使用 Xstream 進行序列化, 進行系統邏輯後續處理。

   

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 概述 iptables是linux自帶的防火牆軟體,用於配置IPv4數據包過濾或NAT(IPv6用ip6tables)。 在linux上,防火牆其實是系統內核的一部分,基於Netfilter構架,基本原理就是在內核網路層數據包流經的不同位置放置一些鉤子(hook),利用這些嵌入網路層的hook來對數 ...
  • 工作原理見書《51單片機應用及原理——基於KeilC和Proteus,陳海宴》P178-180 ...
  • 《鳥哥的Linux私房菜 (基礎學習篇 第三版)》是頗具知名度的Linux入門書《鳥哥的Linux私房菜:基礎學習篇》的全新版,全面而詳細地介紹了Linux操作系統。 全書分為5個部分:第一部分著重說明Linux的起源及功能,如何規劃和安裝Linux主機;第二部分介紹Linux的文件系統、文件、目錄 ...
  • 前言 ASP.NET Core 的變化和發展速度是飛快的,當你發現你還沒有掌握 ASP.NET Core 1.0 的時候, 2.0 已經快要發佈了,目前 2.0 處於 Preview 1 版本,意味著功能已經基本確定,還沒有學習過 ASP.NET Core 的同學可以直接從 2.0 開始學起,但是如 ...
  • Html 內容 Html就是超文本標記語言的簡寫,是最基礎的網頁語言。 Html是通過標簽來定義的語言,代碼都是由標簽所組成。 Html代碼不用區分大小寫。 Html代碼由<html>開始</html>結束。裡面由頭部分<head></head>和體部分<body></body>兩部分組成。 頭部分 ...
  • C#事件總結與應用 什麼是事件? 事件是特殊化的委托,委托是事件的基礎,所以在介紹事件之前先介紹一下委托 通俗的說就是: 事件就是消息驅動器通過委托類來調用感興趣的方法,事實上事件調用是間接的調用 就像是顯示中我的代理人一樣 發佈者與訂閱者 在學習事件的時候們首先要明白什麼是發佈者什麼是訂閱者: 通 ...
  • 一、constant 該函數可以將變數註冊在模塊中,並以服務的形式進行使用。 例如: var app = angular.module("MyModule",[]).constant("pageConfig",{pageSize:10}); 通過以上方式就定義了一個模塊中可用的pageConfig的 ...
  • CentOS上實現一鍵Maven打包並部署到Tomcat的Shell腳本 給這個Shell腳本取個名字,比如叫 deploylab, 將deploylab移到任何已經在系統環境變數的bin目錄下,如: 然後就可以在任意位置直接輸入命令 deploylab 一鍵部署最新代碼到Tomcat了。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...