1、XML是什麼?做用是什麼?css
l XML ( eXtensible Markup Language )語言是一種可擴展的標記語言。其中的可擴展是相對HTML來講的。由於XML標籤沒有被預約義,須要用戶自行定義標籤。java
l XML 被設計的宗旨是:是表示數據,而非顯示數據。node
做用:程序員
l Java開發中,傳統的配置文件是*.properties屬性文件(key=value),而XML表示的數據更爲豐富。web
l XML技術除用於描述有關係的數據外,還常常用做軟件配置文件,以描述程序模塊之間的關係。如:正則表達式
這樣的關係數據該如何處理?編程
用XML語言處理:app
總結:在XML語言中,它容許用戶自定義標籤,一個標籤用於描述一段數據,一個標籤分爲開始標籤和結束標籤,在這二者之間又可使用其它標籤描述其餘數據,以此來實現數據關係的描述。less
2、XML的基本語法 dom
1、文檔聲明
文檔的聲明必須出如今第一行,以前連空行和註釋都不能有.
文檔聲明, 最簡單的語法: <?xml version="1.0"?>
encoding="UTF-8", 若是不添加,默認的採用的是UTF-8編碼,保存在磁盤上的編碼要與聲明的編碼同樣!
standalone屬性,用來講明文檔是否獨立,即文檔是否依賴其餘文檔。
<?xml version="1.0" encoding="utf-8"?>
2、元素
1) xml 元素是指xml中的標籤。一個標籤分爲開始標籤和結束標籤:
a) 包含標籤主體:<mytag>some content</mytag>
b) 不含標籤主體:<mytag/>
2) 一個XML文檔必須有且僅有一個根標籤,其餘標籤都是這個根標籤的子標籤或孫標籤。
3) 一個標籤中能夠嵌套若干子標籤,但全部標籤必須合理的嵌套,不容許有交叉嵌套。
4) xml 中的空格與換行不會被忽略,會當作原始內容被處理.
5) 一個XML元素能夠包含字母、數字以及其它一些可見字符,但必須遵照下面的一些規範:
a) 區分大小寫,例如,<P>和<p>是兩個不一樣的標記。
b) 不能以數字或"_" (下劃線)開頭。
c) 不能以xml(或XML、或Xml 等)開頭。
d) 不能包含空格。
e) 名稱中間不能包含冒號(:) (有特殊用途)。
3、屬性
1) 一個標籤能夠有多個屬性,每一個屬性都有它本身的名稱和取值,例如: <mytag name="value"/>
2) 屬性值必定要用雙引號(")或單引號(')引發來
3) 定義屬性必須遵循與標籤相同的命名規範
4) 在XML技術中,標籤屬性所表明的信息,也能夠被改爲用子元素的形式來描述。
4.註釋
註釋的語法: <!--這是註釋哦.-->
註釋不能寫在第一行.
註釋不可以嵌套.
1 <?xml version="1.0" encoding="utf-8"?> 2 <!-- 註釋 --> 3 <書架> 4 <書 出版社="中國上海"> 5 <名字>誅仙</名字> 6 <做者>蕭鼎</做者> 7 <價格>32.00</價格> 8 <出版日期>2007年</出版日期> 9 </書> 10 <書 出版社="中國北京"> 11 <名字>笑傲江湖</名字> 12 <做者>金庸</做者> 13 <價格>50.00</價格> 14 </書> 15 </書架>
5.CDATA區
用於將一段內容當作普通文本.
語法:<![CDATA[
文本內容
]]>
6.特殊字符
& & ampersand
< < less than
> > great than
" &;quot; quotation
' ' apostrophe
7.處理指令(processing instruction) (PI)
做用:用來指揮軟件如何解析XML文檔
語法: <?xml ?>
如:經常使用的PI指令:
XML聲明:<?xml version=「1.0」 encoding=「GB2312」?>
xml-stylesheet指令:<?xml-stylesheet type = 「text/css」 herf=」test.css」>
<?xml version="1.0" encoding="UTF-8"?> <!-- 這裏用處理命令加入css樣式 --> <?xml-stylesheet type="text/css" href = "PITest.css" ?> <中國> <北京>北京</北京> <上海>上海</上海> <深圳>深圳</深圳> </中國>
PITest.css 文檔以下:
1 @CHARSET "UTF-8"; 2 北京{ 3 font-size: 100px ; 4 color: red; 5 } 6 上海{ 7 font-size: 110px ; 8 color: green ; 9 } 10 深圳{ 11 font-size:100px ; 12 color: yellow ; 13 }
3、XML的約束
一、在XML 技術中能夠編寫一個文檔來約束XML 文檔裏面的書寫規範,這稱爲XML約束。
二、XML 約束技術:
經常使用的有:XML DTD 和 XML Schema
三、XML 約束的必要性:
a) XML都是用戶自定義的標籤,若出現小小的錯誤,軟件程序將不能正確地獲取文件中的內容而報錯.
總結:
格式良好的XML 文檔,遵循語法規則的XML 文檔。
有效的XML 文檔,遵循約束文檔的 XML 文檔。
約束文檔定義了在XML中容許出現的元素名稱、屬性及元素出現的順序等等。
4、DTD的基本語法
1.DTD 約束的兩種方式:
DTD 約束能夠做爲一個單獨的文檔編寫,也能夠編寫在XML 文檔內。(編寫XML內部的DTD代碼),看成爲單獨文件時,要用utf-8格式存儲。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!-- 在XML 寫入DTD 約束 --> 3 <!DOCTYPE 世界[ 4 <!ELEMENT 世界 (國家+) > 5 <!ELEMENT 國家 (名字)> 6 <!ELEMENT 名字 (#PCDATA) > 7 <!ATTLIST 名字 8 所屬洲 CDATA #IMPLIED 9 > 10 <!ATTLIST 國家 所屬洲 (亞洲|歐洲|南美洲|南極洲|澳洲|非洲|北美洲) "亞洲"> 11 ]> 12 13 <世界> 14 <國家 所屬洲 = "亞洲"> 15 <名字>中國</名字> 16 </國家> 17 <國家> 18 <名字 所屬洲 = "美洲">美國</名字> 19 </國家> 20 </世界>
XML 引用 DTD 約束文件時:
1 <?xml version="1.0" encoding="utf-8"?> 2 <!DOCTYPE 書架 SYSTEM "book.dtd" > 3 <書架> 4 <書> 5 <名字>誅仙</名字> 6 <做者>蕭鼎</做者> 7 <價格>32.00</價格> 8 </書> 9 <書 > 10 <名字>笑傲江湖</名字> 11 <做者>金庸</做者> 12 <價格>50.00</價格> 13 </書> 14 </書架>
a)本地的 : <!DOCTYPE 根元素 SYSTEM 「DTD文檔路徑」>
b)互聯網上的: <!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">
注意book.dtd文檔以下:
<!ELEMENT 書架 (書+)> <!ELEMENT 書 (名字,做者,價格)> <!ELEMENT 名字 (#PCDATA)> <!ELEMENT 做者 (#PCDATA)> <!ELEMENT 價格 (#PCDATA)>
DTD 編寫細節:
一、 元素定義
在DTD 文件中用ELEMENT 聲明一個 XML元素,語法:
<!ELEMENT 元素名稱 元素類型>
元素類型能夠是元素內容。
元素內容,則須要用() 括起來,
<!ELEMENT 世界 (國家+) >
<!ELEMENT 國家 (名字,所屬洲)>
<!ELEMENT 名字 (#PCDATA)>
元素類型的組成遵循正則表達式的格式:
一、用逗號分隔,表示內容的出現順序必須與聲明時一致。
<!ELEMENT MYFILE (TITLE,AUTHOR,EMAIL)>
二、用|分隔,表示任選其一,即多個只能出現一個
<!ELEMENT MYFILE (TITLE|AUTHOR|EMAIL)>
三、在元素內容中也可使用+、*、?等符號表示元素出現的次數:
+: 一次或屢次 (書+) regex
?: 0次或一次 (書?)
*: 0次或屢次 (書*)
四、也可以使用圓括號( )批量設置,例
<!ELEMENT FILE ((TITLE*, AUTHOR?, EMAIL)* | COMMENT)>
元素類型,則直接書寫,DTD規範定義了以下幾種類型:
EMPTY:用於定義空元素,例如<br/> <hr/>
ANY:表示元素內容爲任意類型。
二、 屬性定義
xml文檔中的標籤屬性需經過ATTLIST爲其設置屬性
語法格式:
<!ATTLIST 元素名
屬性名1 屬性值類型 設置說明
屬性名2 屬性值類型 設置說明
……
>
設置說明:
#REQUIRED:必須設置該屬性
#IMPLIED:能夠設置也能夠不設置
#FIXED:說明該屬性的取值固定爲一個值,在 XML 文件中不能爲該屬性設置其它值。但須要爲該屬性提供這個值
直接使用默認值:在 XML 中能夠設置該值也能夠不設置該屬性值。若沒設置則使用默認值。但須要爲該屬性提供這個值
經常使用屬性值類型
l CDATA:表示屬性值爲普通文本字符串。
l ENUMERATED
l ID indentity
l ENTITY(實體)
1 <!ELEMENT 國家 (名字)> 2 <!ATTLIST 國家 3 所屬洲 CDATA #REQUEIRED >
三、 實體定義
實體用於爲一段內容建立一個別名,之後在XML 文檔中就可使用別名引用這段內容。
實體可分爲兩種類型:引用實體和參數實體。
引用實體主要在XML 文檔中被使用:
語法格式:<!ENTITY 實體名稱 「實體內容」 >: 直接轉變成實體內容。
引用方式:&實體名稱;
參數實體則是在DTD 文檔中自身使用:
語法格式:<!ELEMENT % 實體名稱 「實體內容」 >
引用方式 :%實體名稱
<!ENTITY % TAG_NAMES "姓名 | EMAIL | 電話 | 地址"> <!ELEMENT 我的信息 (% TAG_NAMES; | 生日)> <!ELEMENT 客戶信息 (% TAG_NAMES; | 公司名)>
5、JUnit 測試類
JUnit 做爲測試工具,能夠經過註釋的方法來代替寫main方法,同時來測試相應的方法:再用JUbit 以前 先導入junit.jar 包。
@Test :用來註釋須要被測試的方法。
@Before : 用來註釋在運行@Test方法以前須要被運行的方法。 注意:若是有多個方法被@Before 註釋,則從最後一個開始運行。
@After : 則註釋在運行@Test方法以後須要被運行的方法。 注意:若是有多個方法被@After 註釋,則從第一個開始運行。
@AfterClass :註釋的方法在類釋放時運行。
@BeforeClass : 註釋的方法在類加載時運行。
1 import org.junit.After; 2 import org.junit.AfterClass; 3 import org.junit.Before; 4 import org.junit.BeforeClass; 5 import org.junit.Test; 6 7 8 public class JUnitDemo { 9 @Test 10 public void test_1() { 11 System.out.println("Hello JUnit!"); 12 } 13 @Before 14 public void before(){ 15 System.out.println("Before"); 16 } 17 @AfterClass 18 public static void afterClass(){ 19 System.out.println("AfterClass"); 20 } 21 @After 22 public void after(){ 23 System.out.println("After"); 24 } 25 @BeforeClass 26 public static void beforeClass(){ 27 System.out.println("BeforeClass"); 28 } 29 }
6、JAXP進行DOM解析
XML 的兩種解析方式:DOM 解析和SAX 解析。
DOM (Document Object Model ,文檔對象模式 ) 解析,原理DOM解析器在解析XML文檔時,會把文檔中的全部元素(document\element\attribute\character),按照其出現的層次關係,解析成一個個Node對象(節點)
在dom中,節點之間關係以下:
一、 位於一個節點之上的節點是該節點的父節點(parent)
二、 一個節點之下的節點是該節點的子節點(children)
三、 同一層次,具備相同父節點的節點是兄弟節點(sibling)
四、 一個節點的下一個層次的節點集合是節點後代(descendant)
五、祖父節點及全部位於節點上面的,都是節點的祖先(ancestor)
Node對象提供了一系列常量來表明結點的類型,當開發人員得到某個Node類型後, 就能夠把Node節點轉換成相應的節點對象(Node的子類對象),以便於調用其特有的方法。
Node對象提供了相應的方法去得到它的父結點或子結點。編程人員經過這些方法就能夠讀取整個XML文檔的內容、或添加、修改、刪除XML文檔的內容了。
練習:
1.讀取節點的文本內容
2.讀取屬性值
3.添加節點
4.刪除節點
5.更新節點
6.打印全部元素節點的名稱.
1 package cn.itheima.xml.day01; 2 3 import javax.xml.parsers.DocumentBuilderFactory; 4 import javax.xml.transform.TransformerFactory; 5 import javax.xml.transform.dom.DOMSource; 6 import javax.xml.transform.stream.StreamResult; 7 8 import org.junit.After; 9 import org.junit.Before; 10 import org.junit.Test; 11 import org.w3c.dom.Document; 12 import org.w3c.dom.Element; 13 import org.w3c.dom.NamedNodeMap; 14 import org.w3c.dom.Node; 15 import org.w3c.dom.NodeList; 16 17 public class DOMTest { 18 /* 19 1.讀取節點的文本內容 20 2.讀取屬性值 21 3.添加節點 22 4.刪除節點 23 5.更新節點 24 6.打印全部元素節點的名稱. 25 */ 26 /* 27 * DOM解析器在解析XML文檔時,會把文檔中的全部元素(document\element\attribute\character),按照其出現的層次關係, 28 * 解析成一個個Node對象(節點)。 29 * 30 * Node對象提供了一系列常量來表明結點的類型,當開發人員得到某個Node類型後, 31 * 就能夠把Node節點轉換成相應的節點對象(Node的子類對象),以便於調用其特有的方法。 32 */ 33 34 //一、讀取節點的文本內容 35 private Document doc = null ; 36 @Test 37 public void readContent() { 38 //得到標籤名爲"名字" 的 NodeList ; 39 NodeList lists = doc.getElementsByTagName("名字") ; 40 //得到節點的文本類容 41 for (int i = 0; i < lists.getLength(); i++) { 42 System.out.println(lists.item(i).getTextContent()); 43 } 44 } 45 //二、讀取屬性值 46 @Test 47 public void getAttr() { 48 //獲取元素「書」的NodeList 49 NodeList lists = doc.getElementsByTagName("書") ; 50 //經過遍歷lists ,獲取每一個節點中的屬性值 51 for (int i = 0; i < lists.getLength(); i++) { 52 NamedNodeMap attributes = lists.item(i).getAttributes(); 53 for (int j = 0; j < attributes.getLength(); j++) { 54 System.out.println(attributes.item(j).getTextContent()); 55 } 56 } 57 } 58 //3.添加節點 59 //在「書」標籤下添加一個<出版日期>的元素 60 @Test 61 public void addNode() throws Exception{ 62 //建立一個<出版日期> 添加到內存中 63 Element element = doc.createElement("出版日期") ; 64 //設置該標籤的的文本值 65 element.setTextContent("2007年"); 66 //經過Node 類中的 appendChild 方法將<出版日期>添加到節點的子節點列表的末尾 67 NodeList lists = doc.getElementsByTagName("書"); 68 69 //問題:爲何只在第二個"書" 標籤添加了該子節點。 70 //並且若是存在<出版日期> 子節點,爲何添加以後有兩個該節點。 71 /* 72 Node appendChild(Node newChild) throws DOMException 73 將節點 newChild 添加到此節點的子節點列表的末尾。若是 newChild 已經存在於樹中,則首先移除它。 74 */ 75 for (int i = 0 ; i < lists.getLength() ; i ++) { 76 System.out.println(lists.item(i).getNodeName()); 77 lists.item(i).appendChild(element) ; 78 } 79 updateXML() ; 80 } 81 82 //如何將修改後的DOC寫到XML中? 83 public void updateXML() throws Exception { 84 /* 85 * javax.xml.transform包中的Transformer類用於把表明XML文件的Document對象轉換爲某種格式後進行輸出 86 * Transformer類經過transform方法完成轉換操做,該方法接收一個源和一個目的地。咱們能夠經過: 87 * > javax.xml.transform.dom.DOMSource 類來關聯要轉換的document對象, 88 * > javax.xml.transform.stream.StreamResult 對象來表示數據的目的地。 89 */ 90 91 //建立TransformFactory 對象: 92 TransformerFactory.newInstance() 93 .newTransformer() 94 .transform(new DOMSource(doc), new StreamResult("src/cn/itheima/xml/day01/book.xml")); 95 } 96 97 //4.刪除節點 98 //刪除「出版日期」節點。 99 @Test 100 public void removeNode() throws Exception { 101 //獲取 "出版日期" 的節點 102 Node node = doc.getElementsByTagName("出版日期").item(0) ; 103 104 //獲取 node 節點的父節點。 105 //經過父節點刪除"出版日期"節點 106 node.getParentNode().removeChild(node) ; 107 updateXML() ; 108 } 109 110 //5.更新節點 111 //將 "笑傲江湖" 的「價格」修改成 50.00 112 /* 113 * 一、獲取「名字」的NodeList , 而後遍歷 值爲「笑傲江湖」 的節點。 114 * 二、獲取「笑傲江湖」節點的兄弟節點。 115 */ 116 @Test 117 public void updateNode() throws Exception{ 118 //獲取「笑傲江湖」的節點 119 NodeList nodeList = doc.getElementsByTagName("名字"); 120 for (int i = 0; i < nodeList.getLength(); i++) { 121 // System.out.println(nodeList.item(i).getTextContent()); 122 if ( nodeList.item(i).getTextContent().equals("笑傲江湖")) { 123 NodeList childNodes = nodeList.item(i).getParentNode().getChildNodes(); 124 for (int j = 0; j < childNodes.getLength(); j++) { 125 if (childNodes.item(j).getNodeName().equals("價格")) { 126 childNodes.item(j).setTextContent("50.00") ; 127 break ; 128 } 129 } 130 } 131 } 132 //經過獲取 其父節點而後經過父節點獲取到「價格」節點,修改其節點的值 133 /*NodeList lists = node.getParentNode().getChildNodes() ; 134 for(int i = 0 ; i < lists.getLength() ; i++) { 135 if( lists.item(i).getNodeName().equals("價格") ) { 136 lists.item(i).setTextContent("50.00"); 137 break ; 138 } 139 }*/ 140 updateXML() ; 141 } 142 //6.打印全部元素節點的名稱. 143 @Test 144 public void printNode(){ 145 treeWeek(doc) ; 146 } 147 public void treeWeek(Node node) { 148 if(Node.ELEMENT_NODE == node.getNodeType()){ 149 System.out.println(node.getNodeName()); 150 } 151 NodeList nl = node.getChildNodes(); 152 for (int i = 0; i < nl.getLength(); i++) { 153 Node item = nl.item(i); 154 treeWeek(item); 155 } 156 } 157 @Before 158 public void getDOM() throws Exception{ 159 /* 160 * 一、得到DocumentBuilderFactory 對象。 161 * 二、經過DocumentBuilderFactory 對象建立 DocumentBuilder 對象(DOM 解析器對象)。 162 * 三、經過DocumentBuilder 對象解析XML文件,進而能夠利用DOM特性對整個XML文檔進行操做了。 163 */ 164 doc = DocumentBuilderFactory.newInstance() 165 .newDocumentBuilder() 166 .parse("src/cn/itheima/xml/day01/book.xml") ; 167 } 168 @After 169 public void setDOM() { 170 doc = null ; 171 } 172 }
總結:
DOM 解析 的優勢是增刪改方便,
缺點,若是要解析的XML 文檔過大,就會致使內存溢出(Out Of Memory , OOM),由於DOM解析須要將XML 文檔內容所有加載到內存中再解析。
7、JAXP進行SAX解析
l SAX (Simple API for XML ) 解析:SAX解析容許在讀取文檔的時候,即對文檔進行處理,而沒必要等到整個文檔裝載完纔對文檔進行操做。
l SAX採用事件處理的方式解析XML文件,利用 SAX 解析 XML 文檔,涉及兩個部分:解析器和事件處理器:
l 解析器可使用JAXP的API建立,建立出SAX解析器後,就能夠指定解析器去解析某個XML文檔。
l 解析器採用SAX方式在解析某個XML文檔時,它只要解析到XML文檔的一個組成部分,都會去調用事件處理器的一個方法,解析器在調用事件處理器的方法時,會把當前解析到的xml文件內容做爲方法的參數傳遞給事件處理器。
l 事件處理器由程序員編寫,程序員經過事件處理器中方法的參數,就能夠很輕鬆地獲得sax解析器解析到的數據,從而能夠決定如何對數據進行處理。
SAX解析步驟:
一、使用SAXParserFactory建立SAX解析工廠
二、經過SAX解析工廠獲得解析器對象
三、經過解析器對象獲得一個XML的讀取器
四、設置讀取器的事件處理器
五、解析xml文件
package cn.itheima.xml.day01; import java.io.IOException; import javax.xml.parsers.SAXParserFactory; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; /* * SAX解析容許在讀取文檔的時候,即對文檔進行處理,而沒必要等到整個文檔裝載完纔對文檔進行操做。 * * SAX採用事件處理的方式解析XML文件,利用 SAX 解析 XML 文檔,涉及兩個部分:解析器和事件處理器: * 解析器可使用JAXP的API建立,建立出SAX解析器後,就能夠指定解析器去解析某個XML文檔。 * * 解析器採用SAX方式在解析某個XML文檔時,它只要解析到XML文檔的一個組成部分(startDocument,startElement,character,endElement,endDocument), * 都會去調用事件處理器的一個方法,解析器在調用事件處理器的方法時, * 會把當前解析到的xml文件內容做爲方法的參數傳遞給事件處理器。 * * 事件處理器由程序員編寫,程序員經過事件處理器中方法的參數, * 就能夠很輕鬆地獲得sax解析器解析到的數據,從而能夠決定如何對數據進行處理。 * javax.xml.parsers.SAXParserFactory * */ /* SAX 解析練習. 1.讀取節點的文本內容 2.讀取屬性值 3.添加節點 4.刪除節點 5.更新節點 6.打印全部元素節點的名稱. 思路: 一、使用SAXParserFactory建立SAX解析工廠 二、經過SAX解析工廠獲得解析器對象 三、經過解析器對象獲得一個XML的讀取器 四、設置讀取器的事件處理器 五、解析xml文件 */ public class SAXTest { private XMLReader reader = null ; //打印出解析出的XML全部內容 @Test public void printTest() throws IOException, SAXException { //設置讀取器的事件處理器: reader.setContentHandler(new MyHandler()) ; reader.parse("src/cn/itheima/xml/day01/book.xml") ; } //1.讀取節點的文本內容 /* * 讀取節點名字爲「名字」的文本內容 */ @Test public void getTextContent() throws IOException, SAXException { reader.setContentHandler(new getTestContent()) ; reader.parse("src/cn/itheima/xml/day01/book.xml") ; } //2.讀取屬性值 /* * 讀取節點名字爲"書" 的屬性值 */ @Test public void getAttributeName() throws IOException, SAXException { reader.setContentHandler(new getAttribute()) ; reader.parse("src/cn/itheima/xml/day01/book.xml") ; } // 在測試以前得到一個XML讀取器: @Before public void getReader() throws Exception { /* 一、使用SAXParserFactory建立SAX解析工廠 二、經過SAX解析工廠獲得解析器對象 三、經過解析器對象獲得一個XML的讀取器 */ reader = SAXParserFactory.newInstance() .newSAXParser() .getXMLReader() ; } //測試完重置reader = null @After public void setReader() { reader = null ; } } class getAttribute extends DefaultHandler { @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if ("書".equals(qName)) { for (int i = 0; i < attributes.getLength(); i++) { System.out.println(attributes.getValue(i)); } } } } class getTestContent extends DefaultHandler{ private boolean flag = false ; @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if ("名字".equals(qName)) { flag = true ; } } @Override public void characters(char[] ch, int start, int length) throws SAXException { if (flag){ System.out.println("文本類容:"+new String(ch,start,length)); flag = false ; } } } //編寫事件處理器: /* 繼承org.xml.sax.helpers.DefaultHandler * DefaultHandler 類: * SAX2 事件處理程序的默認基類。應用程序編寫者能夠在他們僅需實現部分接口時擴展此類; * 相似於ContentHandler 接口的適配器(adapter) ; */ class MyHandler extends DefaultHandler { //在此類中重寫咱們須要的幾個方法: @Override public void startDocument() throws SAXException { System.out.println("XML文件開始解析:"); } @Override public void endDocument() throws SAXException { System.out.println("XML文件解析結束:"); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { System.out.println("元素標籤開始:"+ qName); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { System.out.println("元素標籤結束:" + qName); } @Override public void characters(char[] ch, int start, int length) throws SAXException { System.out.println("文本類容:"+new String(ch,start,length)); } }
總結:優勢查找很是快,可是沒DOM 解析 方法那樣直觀明白。
8、Dom4J簡介、進行解析
Dom4J 則是一層一層的解析XML文件,並且直觀。
1 package cn.itheima.xml.day01; 2 3 import java.io.FileNotFoundException; 4 import java.io.FileOutputStream; 5 import java.io.UnsupportedEncodingException; 6 import java.util.Iterator; 7 import java.util.List; 8 9 import org.dom4j.Attribute; 10 import org.dom4j.Document; 11 import org.dom4j.DocumentException; 12 import org.dom4j.Element; 13 import org.dom4j.io.OutputFormat; 14 import org.dom4j.io.SAXReader; 15 import org.dom4j.io.XMLWriter; 16 import org.junit.After; 17 import org.junit.Before; 18 import org.junit.Test; 19 20 /* 21 * Dom4j是一個很是優秀的Java XML API,具備性能優異、功能強大和極易使用的特色。 22 */ 23 public class DOM4JTest { 24 /* 25 1.讀取節點的文本內容 26 2.讀取屬性值 27 3.添加節點 28 4.刪除節點 29 5.更新節點 30 6.打印全部元素節點的名稱. 31 */ 32 private Document doc = null ; 33 //1.讀取節點的文本內容 34 /* 35 * 讀取"書"節點下,「名字」節點的文本內容 36 * DOM4J 思路: 37 * 1.獲取文檔的根節點. 38 Element root = document.getRootElement(); 39 40 2.取得某個節點的子節點. 41 Element element=node.element(「書名"); 42 43 3.取得節點的文字 44 String text=node.getText(); 45 46 */ 47 @Test 48 public void getNodeText() { 49 //得到跟節點 50 Element root = doc.getRootElement() ; 51 //經過跟節點獲取到子節點 52 List<Element> lists = root.elements() ; 53 for (Element ele : lists) { 54 List<Element> elements = ele.elements() ; 55 for (Element element : elements) { 56 if (element.getName().equals("名字")) 57 System.out.println(element.getText()); 58 } 59 } 60 } 61 //2.讀取屬性值 62 @Test 63 public void getAttribute () { 64 Element root = doc.getRootElement() ; 65 //經過跟節點獲取到子節點 66 List<Element> lists = root.elements() ; 67 for(Element ele : lists) { 68 List<Attribute> attributes = ele.attributes(); 69 for (Attribute attribute : attributes) { 70 System.out.println(attribute.getText()); 71 } 72 } 73 } 74 //3.添加節點 75 /* 76 * 在「書」節點下添加「出版日期」節點。 77 */ 78 @Test 79 public void addNode() throws Exception { 80 Element root = doc.getRootElement() ; 81 for (Iterator<Element> it = root.elementIterator(); it.hasNext() ;) { 82 it.next().addElement("出版日期") 83 .setText("2007年") ; 84 } 85 //寫到XML文件中去。 86 writeToXML() ; 87 } 88 //4.刪除節點 89 /* 90 * 刪除「書」節點下,「名字」爲「笑傲江湖」的「出版日期」的節點。 91 * 思路: 92 * 一、獲取根元素。 93 * 二、經過根元素獲取其子元素,。 94 * 三、遍歷其子元素,獲取子元素的"名字"元素。 95 * 四、若是"名字"元素的值符合條件。 96 * 五、則刪除其兄弟元素"出版日期" 。 97 */ 98 @Test 99 public void removeNode() throws Exception{ 100 Element root = doc.getRootElement() ; 101 // 102 for (Iterator<Element> it = root.elementIterator(); it.hasNext() ;) { 103 Element element = it.next() ; 104 if (element.element("名字").getText().equals("笑傲江湖")) 105 element.remove(element.element("出版日期")) ; 106 } 107 writeToXML() ; 108 } 109 public void writeToXML() throws Exception{ 110 111 //在寫入XML文件時,要設置寫入的編碼格式:utf-8 112 OutputFormat format = OutputFormat.createPrettyPrint(); 113 format.setEncoding("utf-8") ; 114 //最好不要用 FileWriter 寫入,由於,FileWriter 寫入時默認爲系統設定的編碼! 115 XMLWriter writer = new XMLWriter( 116 new FileOutputStream("src/cn/itheima/xml/day01/book.xml"),format ); 117 writer.write( doc ); 118 writer.close(); 119 } 120 @Before 121 public void getDoc() throws Exception { 122 doc = new SAXReader().read( "src/cn/itheima/xml/day01/book.xml"); 123 } 124 @After 125 public void setDoc() { 126 doc = null ; 127 } 128 }
9、XML約束之schema
l XML Schema 文件自身就是一個XML文件,但它的擴展名一般爲.xsd。
l 一個XML Schema文檔一般稱之爲模式文檔(約束文檔),遵循這個文檔書寫的xml文件稱之爲實例文檔。
l 和XML文件同樣,一個XML Schema文檔也必須有一個根結點,但這個根結點的名稱爲Schema。
l 編寫了一個XML Schema約束文檔後,一般須要把這個文件中聲明的元素綁定到一個URI地址上,在XML Schema技術中有一個專業術語來描述這個過程,即把XML Schema文檔聲明的元素綁定到一個名稱空間上,之後XML文件就能夠經過這個URI(即名稱空間)來告訴解析引擎,xml文檔中編寫的元素來自哪裏,被誰約束。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!-- 3 在XML Schema中,每一個約束模式文檔均可以被賦以一個惟一的名稱空間, 4 名稱空間用一個惟一的URI(Uniform Resource Identifier,統一資源標識符)表示 5 6 名稱空間: 7 targetNamespace="http://jbelial.cnblogs.com" 8 URL:http://jbelial.cnblogs.com 根本沒有指向任何文件,只是一個分配的名字。 9 10 elementFormDefault="qualified" 11 12 elementFormDefault元素用於指定, 13 該schema文檔中聲明的根元素及其全部子元素都屬於targetNamespace所指定的名稱空間。 14 15 --> 16 <schema xmlns="http://www.w3.org/2001/XMLSchema" 17 targetNamespace="http://jbelial.cnblogs.com" 18 xmlns:tns="http://www.example.org/NewXMLSchema" 19 elementFormDefault="qualified"> 20 <!-- 規定根元素 --> 21 <element name='書架'> 22 <!-- 根元素下存放複雜數據類型 --> 23 <complexType> 24 <!-- 根元素下的元素的排列方式,和數目爲"未綁定" --> 25 <sequence maxOccurs='unbounded'> 26 <element name='書'> 27 <complexType> 28 <sequence> 29 <!-- 約束:元素的名字,和接收類型: --> 30 <element name="名字" type="string" /> 31 <element name="做者" type="string" /> 32 <element name="價格" type="string" /> 33 </sequence> 34 </complexType> 35 </element> 36 </sequence> 37 </complexType> 38 </element> 39 </schema>
在用Schema 約束XML 文檔時,要注意一下問題:
a)你要建立的xml文檔中的根標籤是什麼?
第一個出現的 <xs:element name='書架' > 就是根標籤
b) 思考: 你使用這個根標籤它來自哪一個名稱空間.
在schema約束文檔中的 targetNamespace="http://jbelial.cnblogs.com" 就是用來講明全部跟標籤綁定在哪一個目標名稱空間上.
c) 思考: 你要引用 schema文檔它與目前名稱空間的對應關係?
須要在xml文檔中添加 xsi:schemaLocation="{namespace} {location}"
{namespace} 就是 : http://jbelial.cnblogs.com
{location} : 引用的schema文檔在哪裏
d) 固定的寫法:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<?xml version="1.0" encoding="UTF-8"?> <p:書架 xmlns:p = "http://jbelial.cnblogs.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jbelial.cnblogs.com NewXMLSchema.xsd"> <p:書> <p:名字>射鵰英雄傳</p:名字> <p:做者>金庸</p:做者> <p:價格>100.00</p:價格> </p:書> </p:書架>
總結:
XML Schema VS DTD