xml基礎知識

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 {

counter++;

System.out.println("\r\n"+counter + ".解析XML文件結束...");}


@Override // 元素開始事件觸發

public void startElement(String uri, String localName, String qName,

Attributes atts) throws SAXException {

counter++;

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 {

counter++;

System.out.print(counter +".</"+qName+">");}


@Override // 文本事件觸發 打印時儘量不要換行,否則很難看

public void characters(char[] ch, int start, int length)throws SAXException {

counter++;

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 java.io.IOException;


import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.parsers.ParserConfigurationException;


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;

import org.xml.sax.SAXException;


/**基於DOM的解析XML文檔*/

public class TestDOMParser {

public static void main(String[] args)

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的順序訪問

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章