天天看點

XML簡介及簡單應用

XML 簡介 可擴充标記型語言

html 裡面的标簽是固定的

XML 标簽可以自己來定義<person></person><貓></貓>

XML用途

可以用于顯示資料和存儲資料(主要功能是存儲)

XML 是w3c組織釋出的技術

1.1版本不能向下相容

XML應用

不同系統之間傳輸資料

QQ之間的資料傳輸

用了表示生活中有關系的資料

經常用在配置檔案

XML的文法

xml的文檔聲明

定義元素(标簽)

定義屬性

注釋

特殊字元

CDTAT區

PI指令 

XML中文亂碼問題解決:儲存和執行編碼表需要一緻

XML元素的定義

标簽的定義 :标簽有開始必須有結束

标簽沒有内容  可以在标簽内結束

标簽可以嵌套 必須合理嵌套:不能交叉

XML把空格換行都當成内容來解析

<aa>aaaaa</aa>

<aa>aaaaa

<aa/>這倆個不一樣、

定義區分大小寫  不能以數字和下劃線開頭

不能以xml XML等開頭

不能包含空格 名稱中間不能包含冒号

XML屬性的定義

     屬性定義的要求

一個标簽上可以有多個屬性

屬性名稱不能相同

屬性值一定要用引号 

  其他和元素定義相同

注釋不能嵌套

XML轉義字元

&  --> &amp

<  --> &lt

>  --> &gt

"  --> &quot

'  --> &apos

XML的CDTAT區 解決頻繁轉義的操作

把需要轉義内容放入CDTAT區就不需要轉義

寫法  <![CDTAT[ 内容 ]]>

PI指令(處理指令)

可以在xml中設定樣式

寫法:<?xml-stylesheet type="text/css" href="css路徑" target="_blank" rel="external nofollow" >對中文不起作用

XML的限制

xml的限制技術 dtd限制 schema限制

dtd快速入門

    ·建立一個檔案 字尾為.dtd

    ·步驟 看xml中有多少元素 有幾個元素,寫幾個<!ELEMENT>

      判斷元素書簡單元素還是複雜元素 

簡單元素就是沒有子元素  <ELEMENT 元素名稱(#PCDATA)>

複雜元素就是有子元素 <!ELEMENT 元素名稱 (子元素)>

      在xml中引入dtd檔案

<!DOCTYPE 根元素名稱 SYSTEM "dtd檔案路徑">

     · 打開xml檔案使用浏覽器打開,浏覽器隻負責校驗xml文法 不檢驗限制

     · 要檢驗xml限制,需要使用工具(myeclise)

       dta的三種引入方式

<!DOCTYPE 根元素名稱 SYSTEM "dtd檔案路徑">

<!DOCTYPE 根元素名稱 [ DTD代碼 ]>

架構多使用<!DOCTYPE PUBLIC "dtd名稱" "dtd文檔url">

使用dtd定義元素

文法 <!ELEMENT 元素名稱 限制>

簡單元素#PCDATA 限制是字元串類型

EMPTY 元素為空

ANY:任意

複雜元素

<!ELEMENT 元素名稱 (子元素)>子元素隻能出現一次

+:表示一次或者多次

?:表示零次或者一次

*:表示任意次

子元素用|隔開  隻能出現任意一個

使用dtd定義屬性

文法: <! ATTLIST 元素名稱 

屬性名稱 屬性類型 屬性的限制 > 

屬性值類型  CDATA 文本字元串

   枚舉 | 每次出現其中一個

   ID 表示屬性取值不能重複

屬性限制設定說明

REQUIRED:該屬性必須出現

IMPLIED:該屬性可有可無

FIXED:屬性的取值為固定值

直接值:表示取值為該預設值

引入實體 定義<!ENTITY 實體名稱 "實體的值">

使用 &實體名稱

·注意 定義實體需要寫在dtd裡面

XML解析的簡介(寫到java代碼)

xml的解析方式 :dom 和 sax

使用dom解析xml 優點友善操作增删改查 缺點是容易記憶體溢出

使用sam解析: 采用事件驅動 邊讀邊解析  不會記憶體溢出 但不能實作增删改操作

         解析xml ,首先需要解析器

     不同的公司群組織 提供了api方式提供

   sun:針對dom 和sax的解析器 jaxp

   dom4j:                    dom4j(實際開發中使用最多)

   jdom:                     jdom

jaxp的api檢視發現

jaxp是javase的一部分

jaxp解析器在jdk的javax.xml.parsers包裡

四個類分别針對dom和sax解析使用的類

dom DocumentBuilder :解析器類 (抽象類)

可以從DocumentBuilderFactory.newDocumentBuilder()中擷取

  一個解析xml的方法  parse(String url) 傳回Document整個文檔

- 傳回的document是一個接口,父節點是Node,如果在document裡面找不到想要的方法,到Node裡面去找

- 在document裡面方法 

getElementsByTagName(String tagname) 

-- 這個方法可以得到标簽

-- 傳回集合 NodeList

createElement(String tagName)

-- 建立标簽

createTextNode(String data) 

-- 建立文本

appendChild(Node newChild) 

-- 把文本添加到标簽下面

removeChild(Node oldChild) 

-- 删除節點

getParentNode() 

-- 擷取父節點

NodeList list

- getLength() 得到集合的長度

- item(int index)下标取到具體的值

for(int i=0;i<list.getLength();i++) {

list.item(i)

}

getTextContent()

- 得到标簽裡面的内容

   DocumentBuilderFactory 解析器工廠(抽象類)

可以從newInstance()擷取

sax SAXparser解析器類

   SAXparserFactory 解析器工廠

使用jaxp實作查詢操作

*** 查詢xml中所有的name元素的值

* 步驟

//查詢所有name元素的值

*** 查詢xml中第一個name元素的值

* 步驟

使用jaxp添加節點

*** 在第一個p1下面(末尾)添加 <sex>nv</sex>

**步驟

使用jaxp修改節點

*** 修改第一個p1下面的sex内容是nan

** 步驟

使用jaxp删除節點

*** 删除<sex>nan</sex>節點

** 步驟

使用jaxp周遊節點

** 把xml中的所有元素名稱列印出來

** 步驟

** 周遊的方法

//遞歸周遊的方法

private static void list1(Node node) {

//判斷是元素類型時候才列印

if(node.getNodeType() == Node.ELEMENT_NODE) {

System.out.println(node.getNodeName());

}

//得到一層子節點

NodeList list = node.getChildNodes();

//周遊list

for(int i=0;i<list.getLength();i++) {

//得到每一個節點

Node node1 = list.item(i);

//繼續得到node1的子節點

//node1.getChildNodes()

list1(node1);

}

}

schema限制

dtd文法: <!ELEMENT 元素名稱 限制>

** schema符合xml的文法,xml語句

** 一個xml中可以有多個schema,多個schema使用名稱空間區分(類似于java包名)

** dtd裡面有PCDATA類型,但是在schema裡面可以支援更多的資料類型

*** 比如 年齡 隻能是整數,在schema可以直接定義一個整數類型

*** schema文法更加複雜,schema目前不能替代dtd

schema的快速入門

* 建立一個schema檔案 字尾名是 .xsd

** 根節點 <schema>

** 在schema檔案裡面

** 屬性  xmlns="http://www.w3.org/2001/XMLSchema"

- 表示目前xml檔案是一個限制檔案

** targetNamespace="http://www.itcast.cn/20151111"

- 使用schema限制檔案,直接通過這個位址引入限制檔案

** elementFormDefault="qualified"

步驟

(1)看xml中有多少個元素

<element>

(2)看簡單元素和複雜元素

* 如果複雜元素

<complexType>
					<sequence>
						子元素
					</sequence>
			</complexType>
           

(3)簡單元素,寫在複雜元素的

<element name="person">
			<complexType>
			<sequence>
					<element name="name" type="string"></element>
					<element name="age" type="int"></element>
			</sequence>
			</complexType>
			</element>
           

(4)在被限制檔案裡面引入限制檔案

<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns="http://www.itcast.cn/20151111"

xsi:schemaLocation="http://www.itcast.cn/20151111 1.xsd">

** xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

-- 表示xml是一個被限制檔案

** xmlns="http://www.itcast.cn/20151111"

-- 是限制文檔裡面 targetNamespace

** xsi:schemaLocation="http://www.itcast.cn/20151111 1.xsd">

-- targetNamespace 空格  限制文檔的位址路徑

* <sequence>:表示元素的出現的順序

<all>: 元素隻能出現一次

<choice>:元素隻能出現其中的一個

maxOccurs="unbounded": 表示元素的出現的次數

<any></any>:表示任意元素

* 可以限制屬性

* 寫在複雜元素裡面

***寫在 </complexType>之前

--

<attribute name="id1" type="int" use="required"></attribute>

- name: 屬性名稱

- type:屬性類型 int stirng

- use:屬性是否必須出現 required

* 複雜的schema限制
<company xmlns = "http://www.example.org/company"
	xmlns:dept="http://www.example.org/department"
	xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.example.org/company company.xsd http://www.example.org/department department.xsd" >
           

* 引入多個schema檔案,可以給每個起一個别名

<employee age="30">

<!-- 部門名稱 --> 

<dept:name>100</dept:name>

* 想要引入部門的限制檔案裡面的name,使用部門的别名 detp:元素名稱

<!-- 員工名稱 -->

<name>王曉曉</name>   

</employee>

sax解析的原理(********)

* 解析xml有兩種技術 dom 和sax

* 根據xml的層級結構在記憶體中配置設定一個樹形結構

** 把xml中标簽,屬性,文本封裝成對象

* sax方式:事件驅動,邊讀邊解析

* 在javax.xml.parsers包裡面

** SAXParser

此類的執行個體可以從 SAXParserFactory.newSAXParser() 方法獲得

- parse(File f, DefaultHandler dh) 

* 兩個參數

** 第一個參數:xml的路徑

** 事件處理器

** SAXParserFactory

執行個體 newInstance() 方法得到

* 畫圖分析一下sax執行過程

* 當解析到開始标簽時候,自動執行startElement方法

* 當解析到文本時候,自動執行characters方法

* 當解析到結束标簽時候,自動執行endElement方法

使用jaxp的sax方式解析xml(**會寫***)

* sax方式不能實作增删改操作,隻能做查詢操作

** 列印出整個文檔

*** 執行parse方法,第一個參數xml路徑,第二個參數是 事件處理器

*** 建立一個類,繼承事件處理器的類,

***重寫裡面的三個方法

* 擷取到所有的name元素的值

** 定義一個成員變量 flag= false

** 判斷開始方法是否是name元素,如果是name元素,把flag值設定成true

** 如果flag值是true,在characters方法裡面列印内容

** 當執行到結束方法時候,把flag值設定成false

* 擷取第一個name元素的值

** 定義一個成員變量 idx=1

** 在結束方法時候,idx+1 idx++

** 想要列印出第一個name元素的值,

- 在characters方法裡面判斷,

-- 判斷flag=true 并且 idx==1,在列印内容

使用dom4j解析xml

* dom4j,是一個組織,針對xml解析,提供解析器 dom4j

* dom4j不是javase的一部分,想要使用第一步需要怎麼做?

*** 導入dom4j提供jar包

-- 建立一個檔案夾 lib

-- 複制jar包到lib下面,

-- 右鍵點選jar包,build path -- add to build path

-- 看到jar包,變成奶瓶樣子,表示導入成功

* 得到document

SAXReader reader = new SAXReader();

        Document document = reader.read(url);

* document的父接口是Node

* 如果在document裡面找不到想要的方法,到Node裡面去找

* document裡面的方法 getRootElement() :擷取根節點 傳回的是Element

* Element也是一個接口,父接口是Node

- Element和Node裡面方法

** getParent():擷取父節點

** addElement:添加标簽

* element(qname)

** 表示擷取标簽下面的第一個子标簽

** qname:标簽的名稱

* elements(qname)

** 擷取标簽下面是這個名稱的所有子标簽(一層)

** qname:标簽名稱

* elements()

** 擷取标

使用dom4j查詢xml

* 解析是從上到下解析

* 查詢所有name元素裡面的值

* 查詢第一個name元素的值

* 擷取第二個name元素的值

使用dom4j查詢xml

* 解析是從上到下解析

* 查詢所有name元素裡面的值

* 查詢第一個name元素的值

* 擷取第二個name元素的值

7、使用dom4j實作添加操作

* 在第一個p1标簽末尾添加一個元素 <sex>nv</sex>

* 步驟

使用dom4j實作在特定位置添加元素 

* 在第一個p1下面的age标簽之前添加 <school>ecit.edu.cn</schlool>

* 步驟

** 可以對得到document的操作和 回寫xml的操作,封裝成方法

** 也可以把傳遞的檔案路徑,封裝成一個常量

*** 好處:可以提高開發速度,可以送出代碼可維護性

- 比如想要修改檔案路徑(名稱),這個時候隻需要修改常量的值就可以了,其他代碼不需要做任何改變

使用dom4j實作修改節點的操作

* 修改第一個p1下面的age元素的值 <age>30</age>

* 步驟

使用dom4j實作删除節點的操作

* 删除第一個p1下面的<school>ecit</school>元素

* 步驟

使用dom4j擷取屬性的操作

* 擷取第一個p1裡面的屬性id1的值

* 步驟

//得到document

Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);

//使用selectNodes("//name")方法得到所有的name元素

List<Node> list = document.selectNodes("//name");

//周遊list集合

for (Node node : list) {

//node是每一個name元素

//得到name元素裡面的值

String s = node.getText();

System.out.println(s);

}

** 使用xpath實作:擷取第一個p1下面的name的值

* //p1[@id1='aaaa']/name

* 使用到 selectSingleNode("//p1[@id1='aaaa']/name")

* 步驟和代碼

//得到document

Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);

//直接使用selectSingleNode方法實作

Node name1 = document.selectSingleNode("//p1[@id1='aaaa']/name"); //name的元素

//得到name裡面的值

String s1 = name1.getText();

System.out.println(s1);