XML(eXtensible Markup Language)是網際網路聯盟(World Wide Web Consortium W3C)定義的一種可擴充标志語言。
可擴充性指允許使用者按照XML規則自定義标記(tags 标簽)。
強項:輕松表達多層結構的資料;可擴充。
優點:平台無關,語言無關。設計目标是描述資料并集中于資料的内容,與顯示分離。
提醒:不能用XML來直接寫網頁。即便是包含了XML資料,依然要轉換成HTML格式才能在浏覽器上顯示。
文法規則:
XML檔案有且僅有一個根标記,其他标記必須封裝在根标記中,檔案的标記必須形成樹狀結構。
大小寫敏感。
标記的屬性必須用""或''括起來。
XML細節:
一、 聲明
大多數XML文檔以XML聲明作為開始,它向解析器提供了關于文檔的基本資訊。
建議使用XML聲明,但它不是必需的。如果有的話,那麼它一定是文檔的第一行内容。
如:<?xml version="1.0" encoding="UTF-8" standalone="no"?>
聲明最多可以包含三個名稱-值對(許多人稱它們為屬性,盡管在技術上它們并不是)。
<?xml 問号與xml之間不能有空格。
1)version 是使用的XML 版本:1.0, 1.1
2)encoding 是該文檔所使用的字元集。該聲明中引用的ISO-8859-1 字元集包括大多數西歐語言用到的所有字元。
預設字元在UTF-8字元集中,這是一個幾乎支援世界上所有語言的字元和象形文字的Unicode 标準。
3)standalone(可以是yes 或no)定義了是否孤立處理該文檔。
如果XML文檔沒有引用任何其它檔案,則可以指定 standalone="yes"。
如果XML文檔引用其它描述該文檔可以包含什麼的檔案(如DTD),則 standalone="no"。預設值為"no"
二、 标記
左尖括号“<“和右尖括号“>“之間的文本
1. 在< >中的稱為開始标記;在</ >中的稱為結束标記
2. 空标記:不包含元素的标記。空标簽必須以“/>”結束。格式: <空标記的名稱/> <空标記的名稱 屬性清單/>
注意:
除空标記外,标簽必須成對:有始有終。所有的開始标簽和結束标簽必須比對。
在标記符“<“和"标記的名稱"之間不能含有空格。在标記符"/>"前面可以有空格或回行。
标簽必須嵌套正确。
XML标記必須遵循下面的命名規則:
1.名字中可以包含字母、數字以及其它字母或文字;還可包含下劃線(_)、點(.)、連字元(-)
2.名字不能以數字開頭;可以用字母、文字或者下劃線開頭。
3.名字不能以字母xml (或XML 或Xml ..) 開頭;
4.名字中不能包含空格。
三、 元素
位于開始标記與結束标記間
一份文檔有且隻有一個根元素。
根元素下的所有元素叫“子元素”。
不包含自子元素的元素叫“葉子”;包含子元素的元素叫“分支”。
如: <eric>…… </eric>
四、 屬性
一個元素的開始标志中的名稱-值對
所有的屬性值必須位于單引号或雙引号中。
每一個元素的屬性不允許出現超過一次。
開始标志内,類似指派語句
如:<eric age="80">……</eric>
五、 注釋
注釋可以出現在文檔的任何位置。(但不建議放在聲明前面,部分浏覽器會報錯)
注釋以 <!-- 開始,以 --> 結束。
注釋内不能包含雙連字元(--);除此之外,注釋可以包含任何内容。
注釋内的任何标記都被忽略
六、 處理指令
處理指令是為使用一段特殊代碼而設計的标記,簡稱為PI。
大多數XML 文檔都是以XML 聲明開始,該聲明本身就是特殊的處理指令。
處理指令對應用程式特定的資料進行編碼。一條處理指令包含一個目标,後跟資料。用<?和?>定界符将處理指令包起來。
目标确定應用程式,而對應用程式不能識别的目标,其會忽略這些處理指令。
七、 實體
XML 規範預定義了五個實體。
&lt; ==== <
&gt; ==== >
&quot; ==== ”
&apos; ==== ‘
&amp; ==== &
自定義實體:在DTD中定義 <!ENTITY 實體标志 "實體内容">
在xml中引用自定義實體,用 &實體标志; 代表實體内容。
另外,無法從鍵盤輸入的字元可以使用字元引用,就是用字元的Unicode代碼點來引用該字元。
以"&#x"開始字元引用,以分号結尾,x必須為小寫,使用十六進制。如: &#x003D; 表示等于号。
也可以使用字元引用來引用 <,>,',",& "
檢視字元的代碼點(附件-> 系統工具-> 字元映射表)。
八、 CDATA
當一段文本中出現很多實體引用和字元引用時,會導緻文本資料的讀寫困難,CDATA段就是為了解決這一問題引入的。
DATA區段開始于 "<![CDATA[" 結束于 "]]>"
CDATA内部的所有東西都會被解析器忽略解析,不用檢查它的格式。
但是CDATA段中不能嵌套另一個CDATA段。
九、 屬性
屬性是标記的屬性,可以為标記添加附加資訊。
(1)屬性的組成
屬性是一個名值對,必須由名稱和值組成,屬性必須在标記的開始标記或空标記中聲明,用"="為屬性指定一個值。
文法如下:
<标記名稱 屬性清單/>
<标記名稱 屬性清單>XXX</标記名稱>
例如: <桌子 width="40" height='100'/>
(2)使有屬性的原則
屬性不展現資料的結構,隻是資料的附加資訊;
一個資訊是作為一個标記的屬性或子标記,取決于具體問題,不要因為屬性的頻繁使用破壞XML的資料結構。
下面是一個結構清晰的XML檔案:
<樓房 height="23m" width="12m">
<結構>混凝土</結構>
<類别>商用</類别>
</樓房>
下面是一個結構不清晰的XML檔案:
<樓房 height="23m" width="12m" 結構="混凝土" 建築商="華海集團" 類别="商用"></樓房>
十、 名稱空間/包
XML檔案允許自定義标記,是以可能出現同名字的标記,為了區分這些标記,就需要使用名稱空間。
名稱空間的目的是有效的區分相同的标記,其實并不真實存在。
文法: 聲明有字首的名稱空間 xmlns:字首名=名稱空間的名字
聲明無字首的名稱空間 xmlns=名稱空間的名字 (預設)
注意:當且僅當它們的名字相同時稱二個名稱空間相同,也就是說,對于有字首的名稱空間,如果二個名稱空間的名字相同,即使字首不相同,也是相同的名稱空間,返之同然。字首隻是友善引用而已。
基本術語
一、序言Prolog:包括XML聲明(XML Declaration)和文檔類型聲明(Document Type Declaration)。
二、良構(well-formed 規範的):符合W3C定義的XML文檔。
驗證
為什麼需要驗證?
對XML檔案施加額外的限制,以便交流。
一、DTD驗證
文檔類型定義(Document Type Definition)
DTD定義了XML文檔内容的結構,保證XML以一緻的格式存儲資料。精确的定義詞彙表,對XML的内容施加限制。
符合DTD的規範XML文檔稱為有效的文檔。由DTD定義的詞彙表以及文檔文法,XML解析器可以檢查XML文檔内容的有效性。
規範的XML檔案不一定是有效的;有效的一定是規範的。
1、 DTD聲明
1) DTD聲明可以在單獨的一個檔案中
2) DTD聲明可以内嵌在XML檔案中
3) DTD聲明可以一部分在單獨的檔案中,另一部分内嵌在XML檔案中
2、 引入外部DTD檔案
<!DOCTYPE data SYSTEM "Client.dtd">
Data:根節點名稱
Client.dtd:dtd檔案路徑
3、 DTD四種标記聲明
元素(ELEMENT)、屬性(ATTLIST)、實體(ENTITY)、符号(NOTATION)
1) 元素(ELEMENT) XML元素類型聲明
聲明元素: <!ELEMENT elementName (contentModel)>
元素的内容通過内容模式來描述。
DTD 内容模式的種類有:
EMPTY 元素不能包含任何資料,但可以有屬性(前提是必須聲明其屬性)。
不能有子元素。不能有文本資料(包括空白,換行符)。
DTD中定義: <!ELEMENT elementName EMPTY>
XML中:<elementName/>(推薦) 或者:<elementName></elementName>
(#PCDATA) 規定元素隻包含已析的字元資料,而不包含任何類型的子元素的内容類型。
DTD中定義: <!ELEMENT student (#PCDATA)>
XML中合法内容: <student>watching TV</student>
(Elements) 元素由内容模式部件指定。
<!ELEMENT name (child particles) >
内容模式部件可以是下表列出的内容。
<!ELEMENT name (a,b)> 子元素a、b必須出現,且按照清單的順序
<!ELEMENT name (a|b)> 選擇;子元素a、b隻能出現一個
<!ELEMENT name (a) > 子元素a隻能且必須出現一次
<!ELEMENT name (a)+ > 子元素a出現一次或多次
<!ELEMENT name (a)* > 子元素a出現任意次(包括零次、一次及多次)
<!ELEMENT name (a)? > 子元素a出現一次或不出現
Mixed 混合模式:子元素中既可有文本資料又可有下級子元素。
<!ELEMENT rn (#PCDATA| an | en)*>“|”和“*”必須寫。
上句表示在 rn 内,字元資料 或 en及an 可以出現任意多次,順序不限。
優先寫(#PCDATA) 如:(#PCDATA|name)* 正确 (name|#PCDATA)* 錯誤
ANY 元素可以包含任何類型的資料。子元素(必須在DTD中有定義) 和 文本資料(包括空白)。
DTD中定義: <!ELEMENT a ANY> <!ELEMENT b ANY>
XML中合法内容: <a>somngthing</a> 或者 <a/> 或者 <a><b>oo</b></a>
2) 屬性(ATTLIST) 特定元素類型可設定的屬性&屬性的允許值聲明
<!ATTLIST elementName
attributeName1 attributeType attributeDefault
.......
attributeNameN attributeType attributeDefault>
屬性類型 (Attribute Type):
CDATA該屬性隻能包含字元資料(注意與CDATA段、PCDATA的差別)
NMTOKEN 是CDATA的子集,它的字元隻能是字母,數字,句點,破折号,下劃線或冒号。
NMTOKENS 類似NMTOKEN,但這個可以包含多個值,每個值之間用空格隔開。
ID 該屬性的取值在同一文檔内是唯一的。一個元素隻能有一個ID類型的屬性。
IDREF 類似指針,指向文檔中其他地方聲明的ID值。如果該屬性取值和指向的ID值不比對,則傳回錯誤。
IDREFS 類似IDREF,但它可以具有由空格分隔開的多個引用。
ENTITY 該屬性的值必須對應一個在文檔内部聲明的但還沒有分析過的實體。
ENTITYS 類似ENTITY,但它可以包含由空格分隔開的多個實體。
NOTATION 該屬性的值必須引用在文檔中其他地方聲明的某個注釋的名稱。
(enumerated) 類似枚舉的變量,該屬性必須比對所列的值。各值用“|”分隔開。
如: (春|夏|秋|冬) 實際内容文檔隻能從中取一個。
屬性特性 (Attribute Default) :
#REQUIRED 必須有且隻能有一個屬性。
#IMPLIED 可有可無。
#FIXED 在DTD中定義預設值,XML中可以不指定,指定則必須等于該預設值。
attribute-value 如果不指定則用DTD定義的預設值,指定則用指定的值。
<![CDATA[############ 屬性(ATTLIST)的舉例 ############## ]]>
例一(#REQUIRED)
DTD中: <!ELEMENT el (#PCDATA)> <!ATTLIST el at1 NMTOKENS #REQUIRED at2 CDATA #REQUIRED>
XML中,正确: <el at1 = "10 20" at2="10" >something</el>
XML中,錯誤: <el at="10">something</el> (沒有寫另一個#REQUIRED的屬性 at2 )
例二(#IMPLIED,#FIXED)
DTD中: <!ELEMENT el (#PCDATA)> <!ATTLIST el at CDATA #FIXED "10" at2 CDATA #IMPLIED >
XML中,正确: <el at2="20" >something</el> (at有預設值"10",at2 可寫可不寫)
XML中,錯誤: <el at="11" >something</el>(at要麼不寫,要寫隻能寫成跟預設值相同的)
例三(attribute-value)
DTD中:<!ELEMENT el (#PCDATA)> <!ATTLIST el at CDATA "10" at2 CDATA "20" >
XML中,正确: <el at="11" >something</el>
例四(enumerated + attribute-value)
DTD中:<!ELEMENT el (#PCDATA)> <!ATTLIST el at (10|20|30) "10">
XML中,正确: <el at="20">something</el> (at要麼不寫,預設值 10;要麼在(10|20|30)中選一個寫)
<![CDATA[############ 屬性(ATTLIST)舉例 完畢 ############## ]]>
3) 實體(ENTITY) 可重用的内容聲明
在DTD中定義 <!ENTITY 實體标志 "實體内容">
在xml中引用自定義的實體,用 &實體标志; 代表實體内容。
4) 符号(NOTATION) 不要解析的外部内容的格式聲明。
3、 内部實體:在xml檔案裡面寫(少用)
外部實體:另外在xml同一檔案夾下建立一個dtd檔案(提倡)
<!--**************** 内外部的實體舉例 ***************** -->
外部的:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE root SYSTEM "goodsInfo.dtd"><!--用這句引用外部dtd-->
<root><goodsInfo>
<goodsName>goodsName</goodsName>
<goodsPrice>goodsPrice</goodsPrice>
</goodsInfo></root>
以下是名為"goodsInfo.dtd"檔案
<!ELEMENT root (goodsInfo)>
<!ELEMENT goodsInfo (goodsName,goodsPrice)>
<!ELEMENT goodsName (#PCDATA)>
<!ELEMENT goodsPrice (#PCDATA)>
内部的:
<?xml version="1.0"?>
<!DOCTYPE root [
<!ELEMENT root(student)>
<!ELEMENT student (#PCDATA)>
<!ENTITY CCTV "中央電視台">
]> <!--把DTD檔案寫在體内-->
<root><student>
student watch &CCTV;<!--使用自定義實體 CCTV-->
</student></root>
<!--***************** 内外部的實體舉例 完畢 ********************** -->
XML處理模式
一、 DOM 文檔對象模式
1.DOM特點:
以樹型結構通路XML文檔。 一棵DOM樹包含全部元素節點和文本節點。可以前後周遊樹中的每一個節點。
整個文檔樹在記憶體中,便于操作;支援删除、修改、重新排列等多種功能。
将整個文檔調入記憶體(包括無用的節點),浪費時間和空間。
一旦解析了文檔還需多次通路這些資料;硬體資源充足(記憶體、CPU)情況下使用。
2.DOM樹與節點
XML文檔被解析成樹型結構。
樹由節點組成。共有12種不同的節點。
節點可以包含其他節點(依賴于節點的類型)。
父節點包含子節點。葉子節點沒有子節點。
3.節點類型
Document node 包含:一個根Element節點。一個或多個處理指令節點。
Document Fragment node
Element node包含:其他Element節點。若幹個Text節點。若幹個Attribute節點。
Attribute node 包含:一個Text節點。
Text node
Comment node
Processing instruction node
Document type node
Entity node
Entity reference node
CDATA section node
Notation node
二、 SAX 基于事件處理模式
解析器向一個事件處理程式發送事件,比如元素開始和元素結束,而事件處理器則處理該資訊。
然後應用程式本身就能夠處理該資料。原始的文檔仍然保留完好無損。
<![CDATA[################## SAX處理器(周遊XML) ###########################]]>
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
public class TestSAXParser {
/** 基于SAX方式解析XML文檔 */
public static void main(String[] args)
throws SAXException,ParserConfigurationException,IOException{
SAXParserFactory factory = SAXParserFactory.newInstance(); //建立SAX解析器工廠
factory.setValidating(true); //讓error方法生效
SAXParser parser = factory.newSAXParser(); //生成一個具體的SAX解析器
parser.parse("src/file/student.xml",new XMLreader()); //開始解析
}}
class XMLreader extends DefaultHandler {
// 隻需覆寫我們感興趣的方法
private int counter = 0;// 定義一個計數器,儲存XML文檔觸發事件的次數
@Override // 文檔開始事件觸發
public void startDocument() throws SAXException {
counter++;
System.out.println(counter + ".解析XML檔案開始...");}
@Override // 文檔結束事件觸發
public void endDocument() throws SAXException {
System.out.println("\r\n"+counter + ".解析XML檔案結束...");}
@Override // 元素開始事件觸發
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
System.out.print(counter+".<"+qName);
for(int i=0; i<atts.getLength();i++){ //讀取标志的所有屬性
System.out.print(" "+atts.getLocalName(i)+"="+atts.getValue(i));
}System.out.print(">"); }
@Override // 元素結束事件觸發
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.print(counter +".</"+qName+">");}
@Override // 文本事件觸發 列印時盡量不要換行,否則很難看
public void characters(char[] ch, int start, int length)throws SAXException {
String text = new String(ch, start, length); // 目前元素的文本值
System.out.print(counter + ".Text=" + text);}
@Override //這是可恢複錯誤。需在SAXParserFactory設定有效性錯誤才能生效
public void error(SAXParseException e) throws SAXException {
System.out.println("xml文檔有效性錯誤:"+e);}
@Override //嚴重錯誤
public void fatalError(SAXParseException e) throws SAXException {
System.out.println("xml文檔嚴重的有效性錯誤:"+e);}
}
<![CDATA[################## SAX處理器(周遊XML)結束 ###########################]]>
三、 DOM
<![CDATA[######################### DOM周遊方式 ###########################]]>
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**基于DOM的解析XML文檔*/
public class TestDOMParser {
throws ParserConfigurationException,SAXException,IOException{
//建立一個DOM解析器工廠
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//從工廠中生成一個DOM解析器; throws ParserConfigurationException
DocumentBuilder builder = factory.newDocumentBuilder();
//綁定需要解析的XML檔案
File xmlFile = new File("src/file/student.xml");//相對位址,相對于這個工程
//開始解析 ;throws SAXException,IOException
Document document = builder.parse(xmlFile);
//取出唯一的根元素
Element rootElement = document.getDocumentElement();
//調用業務方法: 周遊根元素
printElement(rootElement);
/** 周遊元素,包含: 子元素、屬性、文本内容 */
private static void printElement(Element e){
//列印出元素的标簽名
System.out.print("<"+e.getTagName());
//擷取開始标簽的屬性
NamedNodeMap attMap = e.getAttributes();
//循環周遊所有的屬性
for (int i=0;i<attMap.getLength();i++){
Attr attr = (Attr)attMap.item(i);
System.out.print(" "+attr.getName()+"=\""+attr.getValue()+"\"");}
System.out.print(">");
//擷取目前元素的所有子節點
NodeList nl = e.getChildNodes();
for (int j=0;j<nl.getLength();j++){
Node n = nl.item(j);
if (Node.ELEMENT_NODE==n.getNodeType()){
printElement((Element)n);//遞歸調用,以周遊下一個元素
} else {
System.out.print(n.getTextContent());
//列印結束标簽
System.out.print("</"+e.getTagName()+">");
<![CDATA[ ###################### DOM周遊 完畢 ##########################]]>
比較DOM與SAX:
DOM:處理大型檔案時其性能下降的非常厲害。這個問題是由DOM的樹結構所造成的,這種結構占用的記憶體較多,而且DOM必須在解析檔案之前把整個文檔裝入記憶體,适合對XML的随機通路
優點:1.提供随機定義元素操作,來回移動指針
2.将整個XML檔案一次性加載到記憶體,形成虛的記憶體樹
缺點:1.如果XML檔案較大,記憶體空間占用較大
2.強制将較大的XML檔案加載到記憶體中,有可能損害檔案
3.功能通用性
SAX:不同于DOM,SAX是事件驅動型的XML解析方式。它順序逐行讀取XML檔案,不需要一次全部裝載整個檔案。當遇到像檔案開頭,文檔結束,或者标簽開頭與标簽結束時,它會觸發一個事件,使用者通過在其回調事件中寫入處理代碼來處理XML檔案,适合對XML的順序通路