XML和Dom4j的使用
1.1 什麼是XML
-
XML 指可擴充套件標記語言(EXtensibleMarkupLanguage)
-
XML是用來傳輸資料的,不是用來顯示資料的。之後學習另外一個HTML是用來顯示資料的。
-
XML 標籤沒有被預定義。您需要自行定義標籤。
-
XML 是W3C 的推薦標準
W3C在1988年2月釋出1.0版本,2004年2月又釋出1.1版本,但因為1.1版本不能向下相容1.0版本,所以1.1沒有人用。同時,在2004年2月W3C又釋出了1.0版本的第三版。我們要學習的還是1.0版本。
1.2 XML 與 HTML 的主要差異
-
-
html語法鬆散,xml語法嚴格,區分大小寫
-
html做頁面展示,xml傳輸資料
-
html所有標籤都是預定義的,xml所有標籤都是自定義的
-
1.3 xml的作用
-
-
==作為配置檔案。== javaee框架 ssm大部分都會使用xml作為配置檔案
-
XML可以儲存資料 , 作為資料交換的載體(使用XML格式進行資料的傳輸)。
-
小結
-
xml概述: W3C組織釋出的,xml中的所有標籤沒有預定義,標籤區分大小寫, 我們自己可以自定義標籤
-
xml作用: 可以用來儲存資料,作為配置檔案
<?xml version="1.0" encoding="utf-8" ?>
說明:
1.文件宣告可以沒有
2.文件宣告必須在第0行0列
3.文件宣告是以<?xml開頭,以?>結尾
4.文件宣告有2個屬性,version表示xml版本,encoding表示編碼
-
-
標籤分為開始標籤和結束標籤,開始標籤<名字> 結束標籤</名字>
-
開始標籤和結束標籤中間寫的是標籤內容,標籤的內容可以是文字,也可以是其他標籤
-
如果標籤沒有任何內容,那麼可以定義空標籤(比如:<名字/>)
-
標籤可以巢狀,但是不能亂巢狀
-
一個XML檔案只有一個根標籤
-
命名規則: 不要使用XML xML xml 寫樣的單詞
不能使用空格,冒號
命名區分大小寫
<?xml version="1.0" encoding="UTF-8" ?> <person> <name>唐三</name> <age>年齡</age> <aaa/> </person>
屬性
-
位置: 屬性是元素的一部分,它必須出現在元素的開始標籤中,不能寫在結束標籤中
-
格式: 屬性的定義格式:屬性名=“屬性值”,其中屬性值必須使用單引或雙引號括起來
-
一個元素可以有0~N個屬性,但一個元素中不能出現同名屬性
-
屬性名不能使用空格 , 不要使用冒號等特殊字元,且必須以字母開頭
-
空標籤中也可以定義屬性
<?xml version="1.0" encoding="UTF-8" ?> <person> <name id = "001" level = '98'>唐三</name> <age>10</age> <aaa type = 'itheima' /> </person>
<!--註釋內容-->
-
-
註釋不能巢狀
-
idea上快捷鍵:
<price> 蘋果的價格: price > 5 && price < 10</price>
<![CDATA[ 文字資料 ]]> <!--寫步驟 --> <> <!> <![]> <![CDATA]> <![CDATA[ 文字 ]]> <!-- 案例 --> <price> <![CDATA[ 蘋果的價格: price > 5 && price < 10 ]]> </price>
xml約束概述
-
在XML技術裡,可以編寫一個文件來約束一個XML文件的書寫規範,這稱之為XML約束。
-
約束文件定義了在XML中允許出現的元素(標籤)名稱、屬性及元素(標籤)出現的順序等等。
-
兩種約束:DTD約束(檔案字尾為dtd),Schema約束(檔案字尾為xsd)
-
注意: 約束不是我們要寫的東西,我們的工作是根據約束去寫XML
<?xml version="1.0" encoding="UTF-8" ?> <!-- 複製內容如下到XML檔案中: <!DOCTYPE 書架 SYSTEM "bookdtd.dtd"> --> <!-- 對元素的約束: ELEMENT表示這是一個元素 書架表示根標籤 書是書架的子標籤 +數量詞,表示出現的次數,至少出現一次(大於等於1次) --> <!ELEMENT 書架 (書+)> <!--書 這是一個標籤 書標籤中包含書名,作者,售價這些子標籤 ,表示子標籤出現的順序關係--> <!ELEMENT 書 (書名,作者,售價)> <!--書名 這是一個標籤 #PCDATA標籤型別 書名標籤中是文字--> <!ELEMENT 書名 (#PCDATA)> <!ELEMENT 作者 (#PCDATA)> <!ELEMENT 售價 (#PCDATA)> <!--ATTLIST表示對屬性的約束 對書標籤的 id,編號,出版社,type屬性進行約束 --> <!--屬性名為id 屬性的型別為ID(ID型別表示唯一,並且不能以數字開頭) #REQUIRED表示id屬性必須要有 --> <!--屬性名為編號 屬性的型別為CDATA(文字) #IMPLIED表示編號屬性可有可無--> <!--屬性名為出版社 屬性的型別為列舉型別(任選其一) "傳智播客" 預設值為傳智播客--> <!-- 屬性名為type 屬性的型別為CDATA文字 #FIXED表示固定值為 "IT" --> <!ATTLIST 書 id ID #REQUIRED 編號 CDATA #IMPLIED 出版社 (清華|北大|傳智播客) "傳智播客" type CDATA #FIXED "IT" >
-
- XML
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE 書架 SYSTEM "bookdtd.dtd"> <書架> <書 id="a1" 編號="001" 出版社="清華" type="IT"> <書名>斗羅大陸</書名> <作者>唐家三少</作者> <售價>99.8</售價> </書> <書 id="a2"> <書名>java從入門到放棄</書名> <作者>無名氏</作者> <售價>9.8</售價> </書> </書架>
文件宣告(瞭解)
-
內部DTD,在XML文件內部嵌入DTD,只對當前XML有效。
-
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE 根元素 [元素宣告]>><!--內部DTD-->
2.外部DTD—本地DTD,DTD文件在本地系統上,企業內部自己專案使用。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE 根元素 SYSTEM "檔名"><!--外部本地DTD-->
3.外部DTD—公共DTD,DTD文件在網路上,一般都有框架提供 , 也是我們使用最多的.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE 根元素 PUBLIC "DTD名稱" "DTD文件的URL"> 例如: <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
元素宣告(瞭解)
-
約束元素的巢狀層級
語法
<!ELEMENT 父標籤 (子標籤1,子標籤2,…)> 例如: <!ELEMENT books (book+)> <!--約束根元素是"books","books"子元素為"book",“+”為數量詞--> <!ELEMENT book (name,author,price)><!--約束"book"子元素依次為“name”、“author”、“price”,-->
- 約束元素體裡面的資料
-
語法
<!ELEMENT 標籤名字 標籤型別> 例如 <!ELEMENT name (#PCDATA)>
<!ELEMENT name (#PCDATA)> <!ELEMENT author (#PCDATA)> <!ELEMENT price (#PCDATA)>
3.數量詞(掌握)
含義 | |
---|---|
* | 表示元素可以出現0到多個 |
+ | 表示元素可以出現至少1個 |
? | 表示元素可以是0或1個 |
, | 表示元素需要按照順序顯示 |
| |
<!ATTLIST 標籤名稱 屬性名稱1 屬性型別1 屬性說明1 屬性名稱2 屬性型別2 屬性說明2 … > 例如 <!ATTLIST book bid ID #REQUIRED>
屬性型別
-
-
-
CDATA :表示文字字串
-
ID:表示屬性值唯一,不能以數字開頭
-
ENUMERATED (DTD沒有此關鍵字):表示列舉,只能從列舉列表中任選其一,如(雞肉|牛肉|豬肉|魚肉)
-
-
屬性說明:
-
-
-
REQUIRED:表示該屬性必須出現
-
IMPLIED:表示該屬性可有可無
-
FIXED:表示屬性的取值為一個固定值。語法:#FIXED "固定值"
-
-
屬性說明
程式碼
<!ATTLIST 書 <!--設定"書"元素的的屬性列表--> id ID #REQUIRED <!--"id"屬性值為必須有--> 編號 CDATA #IMPLIED <!--"編號"屬性可有可無--> 出版社 (清華|北大|傳智播客) "傳智播客" <!--"出版社"屬性值是列舉值,預設為“傳智播客”--> type CDATA #FIXED "IT" <!--"type"屬性為文字字串並且固定值為"IT"--> >
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE 購物籃 [ <!ELEMENT 購物籃 (肉+)> <!ELEMENT 肉 EMPTY> <!ATTLIST 肉 品種 ( 雞肉 | 牛肉 | 豬肉 | 魚肉 ) "雞肉"> ]> <購物籃> <肉 品種="牛肉"></肉> <肉 品種="牛肉"></肉> <肉 品種="魚肉"></肉> <肉/> </購物籃>
概念
schema和DTD一樣, 也是一種XML檔案的約束.
Schema 語言也可作為 XSD(XML Schema Definition)。
Schema約束的檔案的字尾名.xsd
Schema 功能更強大,資料型別約束更完善。
根據schema約束寫出xml文件
-
-
Schema約束文件:
<?xml version="1.0" encoding="UTF-8" ?> <!-- 傳智播客教學例項文件.將註釋中的以下內容複製到要編寫的xml的宣告下面 複製內容如下到XML檔案中: <書架 xmlns="http://www.itcast.cn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.itcast.cn bookSchema.xsd" > --> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.itcast.cn" elementFormDefault="qualified"> <!--element代表元素 元素名 叫 書架--> <xs:element name='書架'> <!--書架是一個複雜元素--> <xs:complexType> <!--sequence代表子元素要順序出現 unbounded代表子元素可以出現無數次--> <xs:sequence maxOccurs='unbounded'> <!--書架中的子元素叫 書--> <xs:element name='書'> <!--書也是一個複雜元素--> <xs:complexType> <!--書中的子元素是順序出現的--> <xs:sequence> <!--書名是書的子元素 書名是字串型別--> <xs:element name='書名' type='xs:string'/> <!--作者是書的子元素 作者是字串型別--> <xs:element name='作者' type='xs:string'/> <!--售價是書的子元素 售價是小數型別--> <xs:element name='售價' type='xs:double'/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
-
<書架 xmlns="http://www.itcast.cn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.itcast.cn bookSchema.xsd" >
<?xml version="1.0" encoding="UTF-8" ?> <書架 xmlns="http://www.itcast.cn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.itcast.cn bookSchema.xsd" > <書> <書名>斗羅大陸</書名> <作者>唐家三少</作者> <售價>99.8</售價> </書> </書架>
<?xml version="1.0" encoding="UTF-8" ?> <a:書架 xmlns:a="http://www.itcast.cn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.itcast.cn bookSchema.xsd " > <a:書 bid="1"> <a:書名>資料庫從入門到刪庫</a:書名> <a:作者>榮榮</a:作者> <a:售價>99.8</a:售價> </a:書> </a:書架>
-
-
解析方式
-
-
開發中比較常見的解析方式有三種,如下:
-
DOM:要求解析器把整個XML文件裝載到記憶體,並解析成一個Document物件
a)優點:元素與元素之間保留結構關係,故可以進行增刪改查操作。
b)缺點:XML文件過大,可能出現記憶體溢位
-
SAX:是一種速度更快,更有效的方法。她逐行掃描文件,一邊掃描一邊解析。並以事件驅動的方式進行具體解析,每執行一行,都觸發對應的事件。(瞭解)
a)優點:不會出現記憶體問題,可以處理大檔案
b)缺點:只能讀,不能回寫。
-
PULL:Android內建的XML解析方式,類似SAX。(瞭解)
-
-
-
解析器,就是根據不同的解析方式提供具體實現。有的解析器操作過於繁瑣,為了方便開發人員,有提供易於操作的解析開發包
解析包
-
JAXP:sun公司提供支援DOM和SAX開發包
-
Dom4j: 比較簡單的的解析開發包(常用),
-
JDom:與Dom4j類似
-
Jsoup:功能強大DOM方式的XML解析開發包,尤其對HTML解析更加方便(專案中講解)
XML DOM 和 HTML DOM一樣,XML DOM 將整個XML文件載入到記憶體,生成一個DOM樹,並獲得一個Document物件,通過Document物件就可以對DOM進行操作
<?xml version="1.0" encoding="UTF-8"?> <books> <book id="0001"> <name>JavaWeb開發教程</name> <author>張孝祥</author> <sale>100.00元</sale> </book> <book id="0002"> <name>三國演義</name> <author>羅貫中</author> <sale>100.00元</sale> </book> </books>
結構模型
DOM中的核心概念就是節點,在XML文件中的元素、屬性、文字,在DOM中都是節點!所有的節點都封裝到了Document物件中。
-
-
建立解析器
-
讀取xml 獲得document物件
-
得到根元素
-
-
建立解析器物件:
SAXReader sr = new SAXReader();
解析器讀取檔案方法:
Document doc = sr.read(String fileName);
Document的方法:
getRootElement() : 獲取根元素
節點中的方法:
elements() : 獲取當前元素的子元素
getName() : 獲取元素的元素名
getText() : 獲取當前元素的文字值
attributeValue(String name) : 獲取當前元素下某個屬性的值
element(String name) : 根據元素名獲取指定子元素(如果有多個就獲取到第一個)
elementText(String name) : 獲取指定子元素的文字值,引數是子元素名稱
// 建立解析器物件 SAXReader sr = new SAXReader(); // 解析器讀取xml檔案,生產document物件 Document d = sr.read("day16\\books.xml"); // 獲得根元素 Element rootE = d.getRootElement(); // 獲取根元素下的所有子元素 List<Element> list = rootE.elements(); // 迴圈遍歷所有子元素 for (Element e : list) { String id = e.attributeValue("id"); System.out.println("book標籤id的屬性值為:"+id); // 獲取book標籤下的所有子標籤 List<Element> eList = e.elements(); // 迴圈遍歷 for (Element e2 : eList) { // 獲取標籤名 String name = e2.getName(); // 獲取文字值 String text = e2.getText(); System.out.println("標籤名:"+name+",標籤文字內容:"+text); } System.out.println("=================================="); } System.out.println("=================================="); // element(String name) : 根據元素名獲取指定子元素(如果有多個就獲取到第一個) Element eBook = rootE.element("book"); System.out.println(eBook.attributeValue("id"));// 0001 // elementText(String name) : 獲取指定子元素的文字值,引數是子元素名稱 // 獲取第一個book標籤的author子標籤,的文字內容 System.out.println(eBook.elementText("author"));// 張孝祥
步驟1:匯入jar包(dom4j和jaxen-1.1-beta-6.jar)
步驟2:通過dom4j的SaxReader解析器物件,獲取Document物件
步驟3: 利用Xpath提供的api,結合xpat的語法完成選取XML文件元素節點進行解析操作。
document常用的api
獲取XML文件節點元素一共有如下4種XPath語法方式:
-
絕對路徑表示式方式 例如: /元素/子元素/子子元素...
-
相對路徑表示式方式 例如: 子元素/子子元素.. 或者 ./子元素/子子元素..
-
全文搜尋路徑表示式方式 例如: //子元素//子子元素
-
-
獲取型別 | 語法程式碼 |
---|---|
獲取元素節點 | 元素名稱 |
獲取屬性節點 |
-
-
-
<?xml version="1.0" encoding="UTF-8"?> <books> <book id="0001"> <name>JavaWeb開發教程</name> <author>張孝祥</author> <sale>100.00元</sale> </book> <book id="0002"> <name>三國演義</name> <author>羅貫中</author> <sale>100.00元</sale> </book> </books> public class Test { public static void main(String[] args)throws Exception { // 建立SaxReader解析器物件 SAXReader sr = new SAXReader(); // 解析xml檔案,得到Document物件 Document d = sr.read("day16\\books.xml"); // 使用絕對路徑表達方式獲取第一個book的author Element e1 = (Element)d.selectSingleNode("/books/book/author"); System.out.println(e1.getText()); System.out.println("===================="); // 使用絕對路徑表達方式獲取每個book的author List<Element> list = d.selectNodes("/books/book/author"); for (Element e : list) { System.out.println(e.getText()); } } }
<?xml version="1.0" encoding="UTF-8"?> <天氣預報> <北京 provide='京' id='1'> <溫度> <最高溫度 level="A">18</最高溫度> <最低溫度>6</最低溫度> </溫度> <溼度>20%</溼度> </北京> <深圳> <溫度> <最高溫度 level="B">36</最高溫度> <最低溫度>24</最低溫度> </溫度> <溼度>50%</溼度> </深圳> <廣州> <溫度> <最高溫度 level="C">32</最高溫度> <最低溫度>21</最低溫度> </溫度> <溼度>50%</溼度> <黃浦區> <溫度> <最高溫度 level="C">31</最高溫度> <最低溫度>22</最低溫度> </溫度> <溼度>50%</溼度> </黃浦區> <天河區> <溫度> <最高溫度 level="C">30</最高溫度> <最低溫度>26</最低溫度> </溫度> <溼度>50%</溼度> </天河區> </廣州> </天氣預報>
-
public class Test {
public static void main(String[] args)throws Exception {
// 建立SaxReader解析器物件
SAXReader sr = new SAXReader();
// 解析xml檔案,得到Document物件
Document d = sr.read("day16\\tianqi.xml");
// 根據絕對路徑得到北京的溫度標籤
Element e1 = (Element)d.selectSingleNode("/天氣預報/北京/溫度");
// 需求: 以相對路徑獲取北京的最低溫度
Element e2 = (Element)e1.selectSingleNode("./最低溫度");
System.out.println("北京的最低溫度:"+e2.getText());// 6
// 需求: 根據e1標籤,以相對路徑獲取北京的溼度
Element e3 = (Element)e1.selectSingleNode("../溼度");
System.out.println("北京的溼度:"+e3.getText());// 20%
// 需求: 根據e2標籤,以相對路徑獲取北京的溼度
System.out.println(e2.selectSingleNode("../../溼度").getText());// 20%
}
}
-
-
public class Test { public static void main(String[] args)throws Exception { // 建立SaxReader解析器物件 SAXReader sr = new SAXReader(); // 解析xml檔案,得到Document物件 Document d = sr.read("day16\\tianqi.xml"); // 需求:使用全文搜尋路徑的方式,獲取黃浦區的溼度 // 方式一: Element e1 = (Element) d.selectSingleNode("//黃浦區"); System.out.println("黃浦區的溼度: "+e1.elementText("溼度"));// 50% // 方式二: Element e2 = (Element) d.selectSingleNode("//黃浦區//溼度"); System.out.println("黃浦區的溼度: "+e2.getText());// 50% } }
-
謂語,又稱為條件篩選方式,就是根據條件過濾判斷進行選取節點
格式: String xpath1="//元素[@attr1=value]";//獲取元素屬性attr1=value的元素
String xpath2="//元素[@attr1>value]/@attr1"//獲取元素屬性attr1>value的d的所有attr1的值
String xpath3="//元素[@attr1=value]/text()";//獲取符合條件元素體的自有文字資料
String xpath4="//元素[@attr1=value]/html()";//獲取符合條件元素體的自有html程式碼資料。
public class Test { public static void main(String[] args)throws Exception { // 建立SaxReader解析器物件 SAXReader sr = new SAXReader(); // 解析xml檔案,得到Document物件 Document d = sr.read("day16\\tianqi.xml"); // 根據條件篩選,直接獲取深圳的最高溫度 Element e1 = (Element) d.selectSingleNode("//最高溫度[@level='B']"); System.out.println("深圳的最高溫度:"+e1.getText());// 36 System.out.println("============================"); List<Element> list = d.selectNodes("//最高溫度[@level='C']"); for (Element e : list) { System.out.println(e.getText()); } } }