XML 基礎

XML語言

  

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.特殊字符

    &     &amp;    ampersand

    <      &lt;          less than

    >      &gt;         great than

    "      &;quot;   quotation

    '        &apos;    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

  •XML Schema符合XML語法結構。
  •DOM、SAX等XML API很容易解析出XML Schema文檔中的內容。
  •XML Schema對名稱空間支持得很是好。
  •XML Schema比XML DTD支持更多的數據類型,並支持用戶自定義新的數據類型。
  •XML Schema定義約束的能力很是強大,能夠對XML實例文檔做出細緻的語義限制。
  •XML Schema不能像DTD同樣定義實體,比DTD更復雜,但Xml Schema如今已經是w3c組織的標準,它正逐步取代DTD。 
相關文章
相關標籤/搜索