什么是XML
XML(eXtendsible Markup Language)即可標記行擴展語言
XML 可以干啥
- 保存數據
- 用作配置文件
- 數據傳輸載體
XML 文件構成
后綴名
XML 文件都是以 .xml 為后綴
文檔聲明
-
最基本的聲明
<?xml version="1.0" ?>
-
帶編碼(默認為 GBK,一般我們選用 UTF-8),想讓 XML 正常顯示中文,必須保證 encoding 編碼格式與我們文件的編碼保存格式一致
<?xml version="1.0" encoding="UTF-8" ?>
-
關聯文件 (standalone : no - 該文檔依賴關聯其他文檔 yes - 該文檔是一個獨立的文檔)
<?xml version="1.0" encoding="gbk" standalone="no" ?>
元素定義
格式 : 與 HTML 類似,使用 <> 包裹的成為標簽,一般對出現(除了空標簽),例如:
<!-- 成堆出現 -->
<student></student>
<!-- 空標簽,標簽中間並沒有內容,一般配合屬性使用 -->
<age/>
XML 的標簽是可以自定義的,但是必須遵從命名規則
名稱可以含字母、數字以及其他的字符
名稱不能以數字或者標點符號開始
名稱不能以字符 “xml”(或者 XML、Xml)開始
名稱不能包含空格
注: 命名盡量簡單,做到見名知義
元素類型
-
簡單元素
<!-- 簡單元素中間僅包含了普通的文字 --> <student></student>
-
復雜元素
<!-- 復雜元素嵌套其他元素 student就是一個復雜元素 --> <student> <name>張三</name> <age>12</age> </student>
屬性定義
前面說空標簽一般配合屬性使用,當然普通的標簽屬性同樣可以使用
格式:<元素名稱 屬性名稱="屬性的值"></元素名稱>
<stus>
<!-- id 是stu的屬性 -->
<stu id="1001">
<name>張三</name>
<age>18</age>
</stu>
<stu id="1002">
<name>李四</name>
<age>28</age>
</stu>
</stus>
注釋
與 HTML 注釋一樣
<?xml version="1.0" encoding="UTF-8"?>
<!-- 這是一行注釋 -->
注: xml的注釋,不允許放置在文檔的第一行。 必須在文檔聲明的下面。
CDATA
XML 文檔中的文本都會被解析器解析,有時候我們希望某些元素內部的文本不要去解析,比方說下面的student 元素,我們希望他內部的 name ,age 都不要解析為元素,顯然單純下面這種是無法完成這種效果的
<student><name>張三</name><age>12</age></student>
這是為什么呢,這就涉及到 XML的非法字符
<!-- 這種方式是錯誤的 -->
<age> age > 20 </age>
想要解決這個問題,我們必須將非法的字符轉換為實體引用
<!-- 小於號的實體引用為 > -->
<age> age > 20 </age>
XML 預定義實體引用
符號 | 實體引用 |
---|---|
< | < |
> | > |
& | & |
' | ' |
" | " |
注:嚴格地講,在 XML 中僅有字符 "<"和"&" 是非法的。省略號、引號和大於號是合法的,但是把它們替換為實體引用是個好的習慣。
如果我們內部需要使用大量的包含類似標簽和關鍵字(“<” 和 “&”)的這種文字,同時我們又不想要 XML 解析器去解析,此時,我們就需要使用 CDATA 了。
CDATA :是指不應該由 XML 解析器進行解析的文本數據。CDATA 部分的所有內容都會被解析器忽略。
使用格式 :
<![CDATA[ 這里面是文本區域 ]]>
<des><![CDATA[<a href="http://www.baidu.com">百度 && 網址</a>]]></des>
在 CDATA 內部就可以使用 < & 符號而不會報錯了
注: CDATA 部分不能包含字符串 “]]>”,不允許嵌套 CDATA 部分。標記 CDATA 結尾部分“]]>”不能包含空格或拆行。
XML 解析 (Java)
解析XML實際上就是獲取元素的字符數據和屬性數據
常用解析方式
- DOM(可以對文檔進行增刪操作)
- SAX(只能查詢)
DOM(document object model): 把整個xml全部讀取到內存,形成樹狀的結構,整個文檔稱之為document 對象,屬性對應為 attribute 對象,元素節點對應為 element 對象,文本稱之為 text 對象,他們統稱為 node 對象,因為是全部讀入,當xml文件特別大的時候,可能會造成內存溢出。
SAX(simple API for xml): 基於事件驅動,讀取一行解析一行,不會出現內存溢出
解決方案
- jaxp:sun公司
- jdom
- dom4j:使用比較廣泛
dom4j 的基本使用
Maven依賴
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
最基本用法
element.element("stu"); //返回該元素下的第一個stu元素
element.elements(); //返回該元素下的所有子元素。
一般步驟:
- 創建 SaxReader 對象
- 指定解析的 XML
- 獲取根元素
- 根據根元素獲取子元素以及子孫元素
try {
//1. 創建sax讀取對象
SAXReader reader = new SAXReader(); //jdbc -- classloader
//2. 指定解析的xml源
Document document = reader.read(new File("src/xml/stus.xml"));
//3. 得到根元素
Element rootElement= document.getRootElement();
//獲取根元素下面的子元素 age
//rootElement.element("age")
//System.out.println(rootElement.element("stu").element("age").getText());
//獲取根元素下面的所有子元素 。 stu元素
List<Element> elements = rootElement.elements();
//遍歷所有的stu元素
for (Element element : elements) {
//獲取stu元素下面的name元素
String name = element.element("name").getText();
String age = element.element("age").getText();
String address = element.element("address").getText();
System.out.println("name="+name+"==age+"+age+"==address="+address);
}
} catch (Exception e) {
e.printStackTrace();
}
Xpath 使用
使用上面方式獲取子孫節點時會特別的繁瑣,dom4j 支持 Xpath的寫法( xpath其實是xml的路徑語言,支持我們在解析xml的時候,能夠快速的定位到具體的某一個元素)
添加依賴
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1</version>
</dependency>
簡單使用
// 獲取第一個 name 元素
Element nameElement = (Element) rootElement.selectSingleNode("//name");
// 獲取文檔里面的所有name元素
List<Element> list = rootElement.selectNodes("//name");
約束
上面的XML文件中,我們所有的元素都可以隨便寫,像學生的id屬性可以一樣,學生姓名可以有多個...這顯然是不符合現實的。因此我們需要對XML文件作出一定的約束,來控制XML文件滿足我們的要求
約束方式
- DTD
- Schema
DTD
語法自成一派, 早期就出現的, 可讀性比較差
使用方式
-
引用網上的DTD
<!-- 引入dtd 來約束這個xml --> <!-- 文檔類型 根標簽名字 網絡上的dtd dtd的名稱 dtd的路徑 --> <!DOCTYPE stus PUBLIC "//UNKNOWN/" "unknown.dtd">
-
使用本地DTD
<!-- 引入本地的DTD : 根標簽名字 引入本地的DTD dtd的位置 --> <!DOCTYPE stus SYSTEM "stus.dtd">
-
內嵌使用
<!DOCTYPE stus [ <!ELEMENT stus (stu)> <!ELEMENT stu (name,age)> <!ELEMENT name (#PCDATA)> <!ELEMENT age (#PCDATA)> ]>
DTD 編寫格式
<!ELEMENT stus (stu)> stus 下面有一個元素 stu , 但是只有一個
<!ELEMENT stu (name , age)> stu下面有兩個元素 name ,age 順序必須name-age
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ATTLIST stu id CDATA #IMPLIED> stu有一個屬性 文本類型, 該屬性可有可無
<!ELEMENT stu (name , age)> 按照順序來
<!ELEMENT stu (name | age)> 兩個中只能包含一個子元素
元素的個數:
+ 一個或多個
* 零個或多個
? 零個或一個
屬性的類型定義
CDATA : 屬性是普通文字
ID : 屬性的值必須唯一
Schema
其實就是一個xml , 使用xml的語法規則, xml解析器解析起來比較方便 , 是為了替代DTD 。
但是Schema 約束文本內容比DTD的內容還要多。 所以目前也沒有真正意義上的替代DTD
使用scheme約束例子:
約束文件
<!-- xmlns : xml namespace : 名稱空間 / 命名空間
targetNamespace : 目標名稱空間 。 下面定義的那些元素都與這個名稱空間綁定上。
elementFormDefault : 元素的格式化情況。 -->
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.itheima.com/teacher"
elementFormDefault="qualified">
<element name="teachers">
<complexType>
<sequence maxOccurs="unbounded">
<!-- 這是一個復雜元素 -->
<element name="teacher">
<complexType>
<sequence>
<!-- 以下兩個是簡單元素 -->
<element name="name" type="string"></element>
<element name="age" type="int"></element>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</element>
</schema>
被約束文件
<?xml version="1.0" encoding="UTF-8"?>
<!-- xmlns:xsi : 這里必須是這樣的寫法,也就是這個值已經固定了。
xmlns : 這里是名稱空間,也固定了,寫的是schema里面的頂部目標名稱空間
xsi:schemaLocation : 有兩段: 前半段是名稱空間,也是目標空間的值 , 后面是約束文檔的路徑。-->
<teachers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.itheima.com/teacher"
xsi:schemaLocation="http://www.itheima.com/teacher teacher.xsd">
<teacher>
<name>zhangsan</name>
<age>19</age>
</teacher>
<teacher>
<name>lisi</name>
<age>29</age>
</teacher>
<teacher>
<name>lisi</name>
<age>29</age>
</teacher>
</teachers>
命名空間
一個xml如果想指定它的約束規則, 假設使用的是DTD ,那么這個xml只能指定一個DTD , 不能指定多個DTD 。 但是如果一個xml的約束是定義在schema里面,並且是多個schema,那么是可以的。簡單的說: 一個xml 可以引用多個schema約束。 但是只能引用一個DTD約束。
名稱空間的作用就是在 寫元素的時候,可以指定該元素使用的是哪一套約束規則。 默認情況下 ,如果只有一套規則,那么都可以這么寫
<name>張三</name>
<!-- 添加前綴來避免命名沖突 -->
<aa:name></aa:name>
<bb:name></bb:name>
<!-- 使用命名空間 默認命名空間不需要加命名空間前綴-->
<!-- xmlns:命名空間前綴="命名空間的URL" -->
<h:table xmlns:h="http://www.w3.org/TR/html4/">
<h:tr>
<h:td>Apples</h:td>
<h:td>Bananas</h:td>
</h:tr>
</h:table>
<f:table xmlns:f="http://www.w3school.com.cn/furniture">
<f:name>African Coffee Table</f:name>
<f:width>80</f:width>
<f:length>120</f:length>
</f:table>