Xml解析

有名12138 發表於 2020-11-27

XML(可擴充套件標記語言)

Extensive Markup Language

概述:
xml:即可擴充套件標記語言,xml是網際網路資料傳輸的重要工具,它可以跨越網際網路任何的平臺,不受程式語言和作業系統的限制,可以說它是一個擁有網際網路最高階別通行證的資料攜帶者。xml是當前處理結構化文件資訊中相當給力的技術,xml有助於在伺服器之間穿梭結構化資料,這使得開發人員更加得心應手的控制資料的儲存和傳輸。
xml用於標記電子檔案使其具有結構性的標記語言,可以用來標記資料、定義資料型別,是一種允許使用者對自己的標記語言進行定義的源語言。Xml是標準通用標記語言(SGML)的子集,非常適合Web傳輸。XML提供統一的方法來描述和交換獨立於應用程式或供應商的結構化資料。

通過資料兩端通過統一的格式進行資料的儲存與傳輸,並提供通用的讀取方式

xml的特點及作用:
特點:
xml與作業系統、程式語言的開發平臺都無關;
實現不同系統之間的資料互動。
作用:
配置應用程式和網站;
資料互動;
Ajax基石。
在配置檔案裡邊所有的配置檔案都是以XMl的格式來編寫的。

語法:

標題行: <?xml version="1.0" encoding="UTF-8"?>
其餘書寫方式類似於html雙標籤形式書寫,但與html固定標籤不同的是,xml中標籤為自定義,也就是說可以自定義名字標籤

由兩部分組成 標題行與主體(注意:主體中以雙標籤形式進行資料的標誌,根標籤只能有一個,標籤名自定義但通常以儲存資料的類名進行定義)

<!-- 註釋 -->
<!-- 標題行:用於提示讀取者當前文件的類別 以及編碼字符集 -->
<?xml version="1.0" encoding="UTF-8"?>
 
 <!-- 內容:使用指定格式進行資料的儲存 -->
 <!-- 在一個根標籤下進行包裹書寫資料 (注意層級關係) -->
 
 <!-- 例如:儲存Student集合  -->
 <!-- 標籤成對出現 -->
 <students>
	<student>
		<name>張三</name>
		<sex></sex>
		<age>18</age>
	</student>
	<student>
		<name>李四</name>
		<sex></sex>
		<age>28</age>
	</student>
 </students>
import java.io.Serializable;

public class Student implements Serializable {
	private static final long serialVersionUID = -1105845831799085846L;
	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;
	}

	public Student(String name, String sex, String age) {
		super();
		this.name = name;
		this.sex = sex;
		this.age = age;
	}

	public Student() {
		super();
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", sex=" + sex + ", age=" + age + "]";
	}

}

xml解析

①SAX解析

sax解析是xml文件最開始提供的解析方式。

SAX(Simple API for XML)解析器採用了基於事件的模型,它在解析XML文件的時候可以觸發一系列的事件,當發現給定的tag的時候,它可以啟用一個回撥方法,告訴該方法指定的標籤已經找到。SAX對記憶體的要求通常會比較低,因為它讓開發人員自己來決定所要處理的tag.特別是當開發人員只需要處理文件中所包含的部分資料時,SAX這種擴充套件能力得到了更好的體現。但用SAX解析器的時候編碼工作會比較困難,而且很難同時訪問同一個文件中的多處不同資料。

使用流讀取,採用方法回撥進行xml檔案的讀取,在進讀取時如果發現相應的回撥方法則執行

【優點】

​ ①不需要等待所有資料都被處理,分析就能立即開始。
​ ②只在讀取資料時檢查資料,不需要儲存在記憶體中。
​ ③可以在某個條件得到滿足時停止解析,不必解析整個文件。
​ ④效率和效能較高,能解析大於系統記憶體的文件。

【缺點】

​ ①需要應用程式自己負責處理邏輯(例如維護父/子關係等),文件越複雜程式就越複雜。
​ ②單向導航,無法定位文件層次,很難同時訪問同一文件的不同部分資料,不支援XPath。

import java.util.ArrayList;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

//自定義sax解析器
//1自定義sax解析器繼承預設解析器重寫解析方法
public class SaxParseHandler extends DefaultHandler {
	String str = "";
	Student student = null;
	ArrayList<Student> students = new ArrayList<>();

	// 當解析起始標籤時執行方法
	@Override
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
		if (qName.equals("student")) {
			student = new Student();
		}
	}

	// 當解析到結束標籤時執行的回撥方法
	@Override
	public void endElement(String uri, String localName, String qName) throws SAXException {
		if (qName.equals("name")) {
			student.setName(str);
		} else if (qName.equals("sex")) {
			student.setSex(str);
		} else if (qName.equals("age")) {
			student.setAge(str);
		} else if (qName.equals("student")) {
			students.add(student);
		}

	}

	// 當解析文字時執行的回撥方法
	@Override
	public void characters(char[] ch, int start, int length) throws SAXException {
		// ch儲存的是所有位元組資料
		// start當前文字起始位置
		// length當前文字長度
		str = new String(ch, start, length);
	}

	public static void main(String[] args) throws Exception {
		// sax解析xml檔案書寫步驟
		// 1自定義sax解析器繼承預設解析器重寫解析方法
		// 2建立sax解析工廠物件
		SAXParserFactory saxf = SAXParserFactory.newInstance();
		// 3建立sax解析物件
		SAXParser saxp = saxf.newSAXParser();
		// 4建立自定義解析器
		SaxParseHandler sph = new SaxParseHandler();
		// 5使用解析物件執行相應解析器解析xml
		saxp.parse("F://test/students.xml", sph);
		System.out.println(sph.students);
	}
}

②DOM解析

​ DOM(Document Object Model)是用與平臺和語言無關的方式表示XML文件的官方W3C標準。DOM是以層次結構組織的節點或資訊片斷的集合。這個層次結構允許開發人員在樹中尋找特定資訊。分析該結構通常需要載入整個文件和構造層次結構,然後才能做任何工作。由於它是基於資訊層次的,因而DOM被認為是基於樹或基於物件的。

DOM解析是將資料先全部載入下來,之後進行解析可以解析文件任意位置資料

【優點】

​ ①允許應用程式對資料和結構做出更改。
​ ②訪問是雙向的,可以在任何時候在樹中上下導航,獲取和操作任意部分的資料。

【缺點】

​ ①通常需要載入整個XML文件來構造層次結構,消耗資源大。

注意:在使用dom解析是換行文字都會當做節點標籤

import java.io.IOException;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class DomTest {
	public static void main(String[] args) throws Exception {
		ArrayList<Student> list = new ArrayList<>();
		// 1.建立dom解析器工廠物件
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		// 2.使用dom解析器工廠物件建立dom解析器物件
		DocumentBuilder db = dbf.newDocumentBuilder();
		// 3使用dom解析器物件解析指定xml將解析資料儲存在dom物件中
		Document dom = db.parse("F://test/students.xml");
		// 4使用dom物件中的方法獲取資料
		// 獲取dom中所有指定標籤物件
		// NodeList nameList = dom.getElementsByTagName("name");
		// 獲取指定標籤集合長度
		// System.out.println(nameList.getLength());
		// 獲取集合中指定標籤
		// nameList.item(0);//獲取第一個
		// nameList.item(0).getFirstChild();//獲取第一個子標籤
		// nameList.item(0).getFirstChild().getTextContent();//獲取文字標籤資料

		// (1)獲取標籤物件
		NodeList studentNodeList = dom.getElementsByTagName("student");// 獲取所有student標籤物件集合
		// (2)遍歷標籤
		for (int i = 0; i < studentNodeList.getLength(); i++) {
			Student s = new Student();
			// 獲取標籤子節點標籤
			Node node = studentNodeList.item(i);// 獲取指定索引節點標籤
			// 繼續獲取子節點標籤
			NodeList childNodes = node.getChildNodes();
			// 遍歷屬性標籤
			for (int j = 0; j < childNodes.getLength(); j++) {
				// 獲取指定索引節點標籤
				Node item = childNodes.item(j);
				// 判斷是否是文字節點 不是文字節點則繼續獲取子節點標籤
				if (!item.getNodeName().equals("#text")) {
					// 獲取節點標籤資料
					// System.out.println(item.getTextContent());
					if (item.getNodeName().equals("name")) {
						s.setName(item.getTextContent());
					} else if (item.getNodeName().equals("sex")) {
						s.setSex(item.getTextContent());
					} else if (item.getNodeName().equals("age")) {
						s.setAge(item.getTextContent());
					}
				}
			}
			list.add(s);
		}
		System.out.println(list);
	}
}

③JDOM解析

​ JDOM(Java-based Document Object Model)的目的是成為Java特定文件模型,它簡化與XML的互動並且比使用DOM實現更快。由於是第一個Java特定模型,JDOM一直得到大力推廣和促進。正在考慮通過“Java規範請求JSR-102”將它最終用作“Java標準擴充套件”。從2000年初就已經開始了JDOM開發。
​ JDOM與DOM主要有兩方面不同。首先,JDOM使用具體類而不使用介面。這在某些方面簡化了API,但是也限制了靈活性。第二,API大量使用了Collections類,簡化了那些已經熟悉這些類的Java開發者的使用。
​ JDOM文件宣告其目的是“使用20%(或更少)的精力解決80%(或更多)Java/XML問題”(根據學習曲線假定為20%)。JDOM對於大多數Java/XML應用程式來說當然是有用的,並且大多數開發者發現API比DOM容易理解得

多。JDOM還包括對程式行為的相當廣泛檢查以防止使用者做任何在XML中無意義的事。然而,它仍需要您充分理解XML以便做一些超出基本的工作(或者甚至理解某些情況下的錯誤)。這也許是比學習DOM或JDOM介面都更有意義的工作。

​ JDOM自身不包含解析器。它通常使用SAX2解析器來解析和驗證輸入XML文件(儘管它還可以將以前構造的DOM表示作為輸入)。它包含一些轉換器以將JDOM表示輸出成SAX2事件流、DOM模型或XML文字文件。JDOM是在Apache許可證變體下發布的開放原始碼。

【優點】

​ ①使用具體類而不是介面,簡化了DOM的API。
​ ②大量使用了Java集合類,方便了Java開發人員。

【缺點】

​ ①沒有較好的靈活性。
​ ②效能較差。

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

public class JDomTest {
	public static void main(String[] args) throws JDOMException, IOException {
		ArrayList<Student> list = new ArrayList<>();
		// 使用jdom解析xml檔案
		// 1匯入jdom相應jar包
		// 2建立sax解析器(dom一直使用的sax的解析器載入檔案)
		SAXBuilder sb = new SAXBuilder();
		// 3使用sax解析器載入指定xml檔案 返回儲存所有資料的dom物件
		Document dom = sb.build(new File("F://test/students.xml"));
		// 獲取根元素物件
		Element rootElement = dom.getRootElement();
		// 獲取指定元素物件所有子元素
		List<Element> studentList = rootElement.getChildren();
		// 遍歷元素集合
		for (Element student : studentList) {
			Student s = new Student();
           // Student s = new Student(student.getChildText("name"), student.getChildText("sex"), student.getChildText("age"));
			// 獲取每個student元素的子元素(屬性集合)
			List<Element> filedList = student.getChildren();
			// 繼續遍歷屬性集合
			for (Element filed : filedList) {
				if (filed.getName().equals("name")) {
					s.setName(filed.getValue());
				} else if (filed.getName().equals("age")) {
					s.setAge(filed.getValue());
				} else if (filed.getName().equals("sex")) {
					s.setSex(filed.getValue());
					 
				}
			}
			list.add(s);
		}
		System.out.println(list);
	}
}

④DOM4J解析

​ DOM4J(Document Object Model for Java)是JDOM的一種智慧分支。它合併了許多超出基本XML文件表示的功能,為支援所有這些功能,DOM4J使用介面和抽象基本類方法。DOM4J大量使用了API中的Collections類,但是在許多情況下,它還提供一些替代方法以允許更好的效能或更直接的編碼方法。直接好處是,雖然DOM4J付出了更復雜的API的代價,但是它提供了比JDOM大得多的靈活性。

​ DOM4J是一個非常非常優秀的Java XML API,具有效能優異、功能強大和極端易用使用的特點,同時它也是一個開放原始碼的軟體。如今你可以看到越來越多的Java軟體都在使用DOM4J來讀寫XML,特別值得一提的是連Sun的JAXM也在用DOM4J.

【優點】

​ ①大量使用了Java集合類,方便Java開發人員,同時提供一些提高效能的替代方法。
​ ②有很好的效能。

【缺點】

​ ①大量使用了介面,API較為複雜。

import java.io.File;
import java.util.Iterator;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class DOM4JTest {
	public static void main(String[] args) throws Exception {
		// 1匯入dom4j相應jar包
		// 2建立sax解析器物件(dom4j本身沒有解析器,使用sax解析器讀取xml檔案)
		SAXReader saxReader = new SAXReader();
		// 3使用sax解析器讀取指定xml檔案返回dom物件
		Document dom = saxReader.read(new File("F://test/students.xml"));
		// 4獲取根元素物件
		Element rootElement = dom.getRootElement();
		// 5獲取根元素迭代器(迭代所有子元素)
		Iterator iterator = rootElement.elementIterator();
		while (iterator.hasNext()) {// 是否存在下一個元素
			// 如果存在則獲取強轉為元素物件
			Element e = (Element) iterator.next();
			// 繼續遍歷
			// Iterator elementIterator = e.elementIterator();
			// while (elementIterator.hasNext()) {
			// Element e2 = (Element) elementIterator.next();
			// System.out.println(e2.getName()+"=>"+e2.getText());
			// }
			// 獲取指定元素子元素中指定元素物件
			Student s = new Student(e.elementText("name"), e.elementText("sex"), e.elementText("age"));
			System.out.println(s);
		}
	}
}