17.JAVA-Dom、Sax解析XML詳解

来源:https://www.cnblogs.com/lifexy/archive/2019/12/11/12025336.html
-Advertisement-
Play Games

在JAVA中,解析有三種方式: Dom解析(支持改刪,耗記憶體)、 Sax解析(不支持改刪,不耗記憶體)、 Pull解析(在Android中推薦使用的一種解析XML的方式,在下章學習)、 1.支持Dom與Sax解析的開發包 分為兩種. JAXP: 由sun公司推出的解析標準實現(本章只學習該包的解析方法 ...


在JAVA中,解析有三種方式:

  • Dom解析(支持改刪,耗記憶體)
  • Sax解析(不支持改刪,不耗記憶體)
  • Pull解析(在Android中推薦使用的一種解析XML的方式,在下章學習)

 

1.支持Dom與Sax解析的開發包

分為兩種.

  • JAXP:  由sun公司推出的解析標準實現(本章只學習該包的解析方法)
  • Dom4j:  一種開源的解析開發包.

jaxp是java api中自帶的一個包,而dom4j需要我們加入jar文件才能使用

 

2.JAXP使用

JAXP(Java API for XMLProcessing)主要由下麵幾個包組成:

  • org.w3c.dom: 定義DOM解析器的標準介面
  • org.w3c.sax: 定義SAX解析器的標準介面
  • javax.xml:提供解析xml文檔的類
  • javax.xml.parsers:提供了用來獲取DOM和SAX解析器對象的工廠類,比如:DocumentBuilderFactory(創建DOM解析器對象)、SAXParserFactory,如下圖所示:

 

3.使用JAXP進行DOM解析

會將XML文檔全部內容都讀入記憶體中,並且將文檔里的每個數據都創建為一個個對象,所以方便增刪改.並且遍歷簡單。

DOM的缺點主要表現在:效率低,解析速度慢,記憶體占用量過高,對於大文件來說幾乎不可能使用。

3.1 persons.xml示例如下:

<?xml version="1.0" encoding="UTF-8"?>
<persons>
 <person>
    <姓名>張三</姓名>
    <性別></性別>
    <年齡>22</年齡>
  </person>

  <person>
    <姓名>李四</姓名>
    <性別></性別>
    <年齡>17</年齡>
  </person>
</persons>

3.2 DOM讀取xml步驟

1.通過DocumentBuilderFactory.newInstance()靜態方法得到創建 DOM 解析器的工廠對象(DocumentBuilderFactory)

2.通過工廠對象的newDocumentBuilder()方法得到 DocumentBuilder解析器對象

3.然後通過DocumentBuilder解析器對象的parse(filename)方法來得到解析xml文檔的Document對象

4.通過Document對象的成員方法來獲取XML文檔的元素信息,比如getElementsByTagName("person")方法來獲取xml文件中的person元素(返回的類為NodeList,保存person所有的集合,比如list.item(0). getTextContent()列印第一個元素的內容)

具體實現方法如下:

@Test
    public void DomReadXml() throws Exception{
        
     //獲取工廠實例
     DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
     //創建builder
     DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
     //解析xml
     Document document = documentBuilder.parse("src//persons.xml");
     //讀出元素內容
     System.out.println("第一個姓名:"+document.getElementsByTagName("姓名").item(0).getTextContent());
     //讀出元素內容
     System.out.println("第二個姓名:"+document.getElementsByTagName("姓名").item(1).getTextContent());
     
    }

 列印:

 

3.3 DOM修改xml步驟

1.先將xml信息讀取到Document對象

2.然後通過getElementsByTagName("person")方法來獲取xml文件中的person元素(返回的類為NodeList),然後通過NodeList.item(i).setTextContent("text")來修改節點內容

3.修改完成後通過Transformer類的transform(Source , Result )方法來將改過的Document對象寫入XML文件

具體實現方法如下:

  @Test

    public void DomWriteXml() throws Exception{
     DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
     //1.先將xml信息讀取到Document對象中
     Document document = documentBuilder.parse("src//persons.xml");

     //2.修改第一個節點內容為99
     document.getElementsByTagName("年齡").item(0).setTextContent("99");

     //3.通過transform(Source , Result )方法來將改過的Document對象寫入XML文件
     Transformer transformer = TransformerFactory.newInstance().newTransformer();
     Source xmlSource = new DOMSource(document);
     Result outputTarget = new StreamResult("src//persons.xml");
     transformer.transform(xmlSource, outputTarget);
    }

 

4.使用JAXP進行SAX解析

sax解析的優點是邊讀邊解析,占用記憶體少,解析速度快,缺點是不能對XML文件改刪,並且不支持向後遍歷,只能從頭到尾讀取.

4.1 SAX讀取XML步驟

1.獲取SAXParser對象,該對象通過SAXParserFactory構造

2.通過SAXParser.getXMLReader()獲取XMLReder對象

3.實現一個ContentHandler的子類(PersonHandler),其實就是構造一個DefaultHandler的子類(因為contentHandler介面太多方法沒實現),如下圖所示:

然後重寫startElement()等方法(用來實現具體的XML讀取)

4.再調用XMLReder對象的setContentHandler(new PersonHandler())來設置我們要解析的具體handler

5.最後調用XMLReder對象的parse(file),開始進行解析

4.2 Myhandler需要重寫的方法有以下幾個

startDocument();    //當文檔開始解析時,觸發該方法
endDocument();    //當文檔解析完成時,觸發該方法


startElement(String uri, String localName, String qName, Attributes attributes)
//解析到開始元素時,觸發該方法

endElement(String uri, String localName, String qName)
//解析到結束元素時,觸發該方法
//uri:名稱空間URI,如果元素沒有名稱空間,沒有則為空字元串。
//localName:本地名稱(不帶首碼),沒有則為空字元串。
//qName:元素名(帶有首碼),如果元素名不可用則為空字元串。
//attributes:該元素的所有屬性。如果沒有屬性,則為空對象.

characters(char[] ch, int start, int length)
//接收字元內容時,觸發該方法,比如"<姓名>李四</姓名>",當解析到"李四"時,會調用到該方法,並將"李四"作為參數傳遞進來.

4.3 persons.xml示例如下:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persons>
    <person>
    <姓名>張三</姓名>
    <性別></性別>
    <年齡>99</年齡>
    </person>

    <person>
    <姓名>李四</姓名>
    <性別></性別>
    <年齡>17</年齡>
    </person>
</persons>

4.4 Person類如下所示:

public class Person {
    private String name;
    private String sex;
    private String age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public String getAge() {
        return age;
    }
    public void setAge(String age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", sex=" + sex + ", age=" + age + "]";
    }
}

4.5 SaxParseTest類如下所示:

package com.my.xmlparser;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.junit.Test;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import com.my.bean.Person;

class PersonHandler extends DefaultHandler{
    private String status=null;
    private ArrayList<Person> persons=null;
    private Person person=null;
    @Override
    public void startDocument() throws SAXException {
        
        persons = new ArrayList<Person>();
        person = new Person();
    }

    @Override
    public void endDocument() throws SAXException {
        for(Person person1:persons){        //列印所有信息
            System.out.println(person1);
        }
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        status = qName;  
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        status =null;
        if("person".equals(qName))   //添加一個person
        {
            persons.add(person);
            person = new Person();
        }
    }
    
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        String text = new String(ch,start,length);
        if(status == null)
            return;
        else if("姓名".equals(status))
        {
            person.setName(text);
        }
        else if("性別".equals(status))
        {
            person.setSex(text);
        }
        else if("年齡".equals(status))
        {
            person.setAge(text);
        }
    }
}


public class SaxParseTest {

    @Test
    public void SaxParse() throws Exception{
        //1.獲取SAXParser對象,該對象通過SAXParserFactory構造
        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
        SAXParser saxParser = saxParserFactory.newSAXParser();
        
        //2.通過SAXParser.getXMLReader()獲取XMLReder對象
        XMLReader reader = saxParser.getXMLReader();
        //3~4:實現一個ContentHandler的子類(Myhandler),然後來設置我們要解析的具體handler
        reader.setContentHandler(new PersonHandler());
        //5.最後調用XMLReder對象的parse(file),開始進行解析
        reader.parse("src//persons.xml");
    }
}

測試運行:

 

未完待續,下章學習pull解析


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

-Advertisement-
Play Games
更多相關文章
  • Inversion of Control 將創建對象的權利交給框架,包括DI(Dependency Injection,依賴註入)和DL(Dependency Lookup,依賴查找),能削減電腦程式的耦合,即解除代碼中的依賴關係 應用 xml 1. 建立maven工程 2. 導入jar包,pom ...
  • python中的 和 ,能夠讓函數支持任意數量的參數,它們在函數定義和調用中,有著不同的目的 一. 打包參數 的作用:在函數定義中,收集所有的位置參數到一個新的元組,並將這個元組賦值給變數args 的作用:在函數定義中,收集關鍵字參數傳遞給一個字典,並將這個字典賦值給變數kwargs PS:遇到問題 ...
  • 1、find檢測str是否包含在mystr,如果是返回開始的索引值,否則返回 1 2、index和find一樣只不過,str不在mystr中會報一個異常 3、rfind、rindex從右往左找 4、count返回str在start和end之間,在mystr里出現的次數 5、replace把mystr ...
  • Python是面向對象(OOP)的語言, 而且在OOP這條路上比Java走得更徹底, 因為在Python里, 一切皆對象, 包括int, float等基本數據類型. 在Java里, 若要為一個類定義只讀的屬性, 只需要將目標屬性用private修飾, 然後只提供getter()而不提供setter( ...
  • 原創發佈在 https://blog.csdn.net/qq_21484935/article/details/103461778 思路:請求小說的url並對內容進行解析,找到帶有更新時間的span標簽。然後配置郵箱,將內容作為發送。 我選擇的是網易的126郵箱,在官網登錄賬號,設置中,打開“POP ...
  • 一. 基本介紹 1. Lambda Lambda是java 8引入的一個新特性,一個Lambda表達式是一個匿名函數,它提供了更為簡單的語法和協作方式,能夠讓我們通過表達式來代替函數式介面。 Lambda表達式完全可以用在簡化創建匿名內部類上。 2. 函數式介面 所謂的函數式介面,就是指 只有一個抽 ...
  • PHP 從誕生到現在已經有20多年曆史,從Web時代興起到移動互聯網退潮,互聯網領域各種編程語言和技術層出不窮, Node.js 、 GO 、 Python 不斷地在挑戰 PHP 的地位。這些技術的推動者非常熱衷於唱衰 PHP , PHP 語言的未來在哪裡?PHP 程式員當如何應對未來的變革? 作為 ...
  • 對象的產生 當一個對象被創建時,會對其中各種類型的成員變數自動進行初始化賦值,除了基本數據類型之外的變數類型都是引用型。 匿名對象 在創建對象時只有new 和 類名,不將new 出來的值賦給對象名,而是直接調用這個對象的方法。 例如:new Person().shout(); 使用情況 如果對一個對 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...