寫了這么多的配置文件(XML),你真的了解它嗎?


什么是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的非法字符

張三 12 如果不想被解析的話,其所有的字符都要被識別為普通文本,但是 < 字符會被識別為一個元素的開始,我們同樣不能在元素內部使用 > <

<!-- 這種方式是錯誤的 -->
<age> age > 20 </age>

想要解決這個問題,我們必須將非法的字符轉換為實體引用

<!-- 小於號的實體引用為 &gt; -->
<age> age &gt; 20 </age>

XML 預定義實體引用

符號 實體引用
< &lt;
> &gt;
& &amp;
' &apos;
" &quot;

注:嚴格地講,在 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>



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM