# XML
[TOC]
## XML介紹與用途
XML的全稱為EXtensible Markup Language,可擴展標記語言
編寫XML就是編寫標簽,形式與HTML非常類似。通常以文件的方式來保存數據,文件的擴展名為.xml。
>[info]XML和之前講解過的Json作用其實相同的,都是為了保存數據。
> XML沒有預制標簽都是自己定義的。
> XML本身標簽存在一定含義,并且語法格式非常規范,存在良好的人機可讀性
比如:
~~~xml
person.xml
<person>
<name>張三</name>
<age>23</age>
<sex>男</sex>
<height>178</height>
<height>75</weight>
</person>
school.xml
<school>
<class no="J121">
<name>Java全日制121班</name>
<count>5</count>
</class>
<class no="JY3">
<name>Java業余3班</name>
<count>4</count>
</class>
</school>
~~~
**XML與HTML的比較**
1. XML與HTML非常相似,都是編寫標簽
2. XML沒有預定義標簽,HTML存在大量預定義標簽
3. XML重在保存與傳輸數據,HTML用于顯示信息
**XML的用途**
1. Java程序的配置描述文件
比如:web應用配置文件
~~~xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>demo3</display-name>
<welcome-file-list>
<welcome-file>Login2Servlet</welcome-file>
</welcome-file-list>
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>cn.filters.EncodingFilter</filter-class>
<init-param>
<param-name>Encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
</web-app>
~~~
2. 用于保存程序產生的數據
3. 網絡間的數據傳輸
## XML的語法規則
### XML文檔結構
1. 第一行必須是XML聲明
XML聲明說明XML文檔的基本信息,包括版本號與字符集,寫在XML第一行
~~~xml
<?xml version="1.0" encoding="UTF-8"?>
~~~
2. 有且只有一個根節點
3. XML標簽的書寫規則與HTML相同
### XML標簽書寫規則
* 適當的注釋 `<!-- -->`與縮進
* 合理的標簽名
1. 標簽名要有意義
2. 建議使用英文,小寫字母,單詞之間使用`-`進行分割
3. 建議多級標簽之間不要存在重名的情況
* 合理使用屬性
1. 標簽屬性用于描述標簽不可或缺的信息
2. 對標簽分組或者為標簽設置id時常用屬性表示
* 特殊字符與CDATA標簽
標簽體中,出現`<` `>`特殊字符,會破壞文檔結構
如:
~~~xml
<example>
<question>3+4>6</question>
</example>
~~~
可以使用實體引用CDATA標簽解決該問題
1. 實體引用:
| 實體引用 | 對應符號 |
| --- | --- |
| `<` | `<` |
| `>` | `>` |
| `&` | `&` |
| `'` | `'` |
| `"` | `"` |
2. CDATA標簽
CDATA標簽指的是不應由XML解析器進行解析的文本內容,使用`<![CDATA[開始 ~ 結束]]>`將該部分內容包裹起來
* 有序的子元素
指的是在多層嵌套的子元素中,標簽的前后順序應保持一致
## XML語義約束
在XML中文檔結構正確,但可能不是有效的。
比如在關于員工檔案的XML文檔中,不允許出現有關植物品種的標簽,XML語義約束指的就是規定XML文檔中允許出現哪些元素
XML的語義約束有兩種定義方式:DTD和XML Schema;
**DTD**
DTD(Document Type Definition 文檔類型定義),是一種簡單易用的語義約束方式。
DTD文件的擴展名為.dtd
~~~
<!ELEMENT>定義XML文檔允許出現的節點和數量。
例如:定義hr節點下只允許出現一個employee子節點。
<!ELEMENT hr(employee)>
定義hr節點下至少出現一個employee子節點。
<!ELEMENT hr(employee+)>
定義hr節點下可以出現0...n個employee子節點。
<!ELEMENT hr(employee*)>
定義hr節點下可以最多出現一個employee子節點。
<!ELEMENT hr(employee?)>
定義hr節點標簽體只能是文本。
<!ELEMENT hr(#PCDATA)>
定義hr節點只能有四個子節點,并且按順序排列。
<!ELEMENT hr(name,age,salary,department)>
<!ATTLIST>定義XML文檔中元素的屬性。
例如:定義employee節點屬性no的默認值為""
<!ATTLIST employee no CDATA "">
~~~
在XML中使用<!DOCTYPE>標簽引用DTD文件
`<!DOCTYPE 根節點 SYSTEM "dtd文件路徑">`
**XML Schema**
>[info]Schema比dtd更復雜 高級的約束性語言
提供了數據類型 格式限定 數據范圍等特性
Schema 是w3c標準的標準規范
~~~xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 人力資源管理信息 -->
<!-- xmlns:xsi屬性的值用來告訴xml文檔,使用的是schema約束 -->
<employee-data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="hr.xsd">
<employee nid="3309">
<name>張三</name>
<age>24</age>
<salary>5000</salary>
<department>
<dname>會計部</dname>
<address>數字大廈</address>
</department>
</employee>
<employee nid="3310">
<name>李四</name>
<age>25</age>
<salary>5600</salary>
<department>
<dname>開發部</dname>
<address>數字大廈</address>
</department>
</employee>
</employee-data>
~~~
~~~xml
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema">
<element name="employee-data"><!-- 表明根節點是employee-data -->
<!-- complexType標簽含義是復雜節點,包含子節點的時候必須使用這個標簽 -->
<!-- 因為employee是根節點,下面有很多的子節點,所以必須使用 -->
<complexType>
<sequence><!-- 序列:表明其下的子節點必須按照順序前后嚴格書寫 -->
<!-- minOccurs="1" maxOccurs="999"表示該節點最少出現一次,最大出現999次 -->
<element name="employee" minOccurs="1" maxOccurs="999">
<complexType>
<sequence>
<!-- type="string"表明該節點中只能輸入字符串,不能擁有子節點 -->
<element name="name" type="string"></element>
<!-- type="integer"表明該節點中只能輸入數字,不能擁有子節點 -->
<element name="age">
<simpleType>
<restriction base="integer"><!-- 表示數值范圍 -->
<minInclusive value="18"></minInclusive>
<maxInclusive value="60"></maxInclusive>
</restriction>
</simpleType>
</element>
<element name="salary" type="integer"></element>
<element name="department">
<complexType>
<sequence>
<element name="dname" type="string"></element>
<element name="address" type="string"></element>
</sequence>
</complexType>
</element>
</sequence>
<!-- use="required"表示nid屬性在任何employee節點上必須存在 -->
<attribute name="nid" type="string" use="required"></attribute>
</complexType>
</element>
</sequence>
</complexType>
</element>
</schema>
~~~
## Java解析XML
Java可以使用DOM、SAX、DOM4j、JDOM等方式解析XML文檔,最常用的還是屬于DOM4j
DOM4j**jar**包下載地址:[https://dom4j.github.io](https://dom4j.github.io/)
**xml:解析**
~~~java
import java.io.File;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class DOM4jDemo {
public static void main(String[] args) throws Exception {
//1.創建Reader對象
//SAXReader類是讀取XML文件的核心類,用于將XML解析后以“樹”的形式保存在內容中
SAXReader reader = new SAXReader();
//2.加載xml,獲取整個文檔的document對象
Document document = reader.read(new File("src/com/ntdodoke/JDBCStudy/hr.xml"));
//3.獲取根節點
Element rootElement = document.getRootElement();
//或者采用rootElement.elementText("name")方法輸出節點文本值
//創建迭代器準備迭代
Iterator<Element> iterator = rootElement.elementIterator();
while (iterator.hasNext()){
Element stu = iterator.next();
//獲取節點的屬性
List<Attribute> attributes = stu.attributes();
System.out.println("======獲取屬性值======");
for (Attribute attribute : attributes) {
System.out.println(attribute.getValue());
}
System.out.println("======遍歷子節點======");
Iterator<Element> iteratorSon = stu.elementIterator();
while (iteratorSon.hasNext()){
Element stuChild = iteratorSon.next();
System.out.println("節點名:"+stuChild.getName()+"---節點值:"+stuChild.getStringValue());
}
}
}
}
~~~
**xml:修改**
~~~java
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class Demo4jWriter {
public static void main(String[] args) {
writeXml();
}
public static void writeXml(){
String file = "src/com/ntdodoke/JDBCStudy/hr.xml";
SAXReader reader = new SAXReader();
try {
Document document = reader.read(file);
Element root = document.getRootElement();
Element employee = root.addElement("employee");
employee.addAttribute("nid", "3311");
Element name = employee.addElement("name");
name.setText("李鐵柱");
employee.addElement("age").setText("37");
employee.addElement("salary").setText("3600");
Element department = employee.addElement("department");
department.addElement("dname").setText("人事部");
department.addElement("address").setText("數字大廈-B105");
Writer writer = new OutputStreamWriter(new FileOutputStream(file) , "UTF-8");
document.write(writer);
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
~~~
## XPath路徑表達式
**XPath**即為XML路徑語言(XML Path Language),它是一種用來確定XML文檔中某部分位置的語言。
XPath基于XML的樹狀結構,提供在數據結構樹中找尋節點的能力。
XPath路徑是XML文檔中查找數據的語言,掌握XPath可以極大的提高在提取數據時的開發效率。
學習XPath本質就是掌握各種表達式的使用技巧。
**XPath基本表達式**

**XPath基本表達式使用案例**

**XPath謂語表達式**

**Jaxen介紹:**
Jaxen是一個Java編寫的開源的XPath庫,能適應不同的不同的對象模型,包括DOM、XOM、DOM4j和JDOM,DOM4j底層依賴Jaxen實現XPath查詢。
Jaxen下載地址:[https://maven.aliyun.com/mvn/view](https://maven.aliyun.com/mvn/view)
可以到阿里云的鏡像倉庫下載想要的jar包