2018-04-23 20:29:26
XML:Extensible Markup Language,也就是可擴展標記語言。XML和HTML格式是古老的標記通用語言SGML的衍生語言。
XML文件是可以用來作為配置文件的,相比于其他配置文件的規范,XML的好處在于通過自定義的標記,程序可以利用標記尋找相應的配置信息,這樣就可以隨意調整配置信息的位置,標記也能幫助用戶理解配置信息的含義。
我們常常會遇到不同的商業伙伴之間會有密切的商務往來,彼此之間的信息系統需要對接,但是有可能雙方使用的是不同的數據庫產品,雖然這些數據庫都支持SQL92標準,但是經過演變,各種各樣的數據庫或多或少的發展了自己的方言,這樣在不同的數據庫之金啊交換數據,變成了令人頭疼的問題。比如,中國移動使用的是Oracle的工具,而銀行使用的是DB2,那么這兩者的數據交互就會稱為令人頭疼的問題。另外,在企業間合并的時候,多種不同的數據庫之間的合并也會成為麻煩。現在有了XML,一切都變得很容易,因為XML被廣泛的支持,所以XML成為了不同數據庫之間數據遷移的工具。
除了在數據庫領域XML利用自身標準幫助遷移數據,在非數據庫領域,XML也能用來協調不同計算機語言,不同服務器平臺等這些場合的數據融合。
盡管XML和HTML同宗同源,但是兩者之間存在著重要的區別:
- 與HTML不同,XML是大小寫敏感的,例如<H1>和<h1>是不同的XML標簽。
- 在HTML中,如果從上下文可以分清哪里是段落或者列表項的結尾,那么結尾標簽如</p>可以省略,而XML中結束標簽絕對不能省略。
- 在XML中,只有單個標簽而沒有相對應的結束標簽的元素必須以/結尾。這樣解析器就不需要查找形如</p>的標簽了。
- 在XML中,屬性值必須用引號括起來。在HTML中,引號是可有可無的。例如,<applet code = "CodeDemo.class" width = 300>,這在HTML中是合法的,但是在XML中則是不被允許的,需要加上引號進行約束。所以在XML中應該寫成<applet code = "CodeDemo.class" width = “300”>
- 在HTML中,屬性名可以沒有值。例如,<input type = "radio" cheacked>。在XML中所有的屬性都必須要有屬性值。比如,<input type = "radio" cheacked=“true”>
一、XML文檔的結構
1、XML應該以一個文檔頭開始,例如:<?xml version="1.0" encoding="UTF-8"?>。encoding不是必須的,?與xml之間不能有空格,XML語法規定是相當嚴格的。
2、文檔頭之后通常是文檔的文檔類型定義(Document Type Definition,DTD)。
3、XML的標記以<>為開頭,以</>為結尾,完整的這樣一個結構被稱為元素,和html不同的是,html里的元素都是事先規定好的,而XML的標記是作者自己規定的。
XML文檔的正文包含根元素,根元素包含一些其他的元素。元素可以有子元素(child element),文本或者兩者皆有。在下述的例子中,font元素有兩個子元素,它們是name和size。
<?xml version="1.0"?> --文檔頭<!DOCTYPE configuration ...> --文檔的類型定義DTD
<configuration><title><font><name>Java</name><size>36</size></font></title>
...
</configuration>
4、XML其他的一些指令
- 字符引用
字符引用的形式是&#十進制值,或者&#x十六進制值。例如,字符a,a,或者a。
- 實體引用
實體引用的形式是&name,例如<;>;&;";&apos,都有預訂的含義:小于,大于,&,引號,省略號。
- CDATA部分
CDATA部分用<![CDATA[...]]>來限定其界限。它們是字符數據的一種特殊形式。你可以用來囊括那些含有<,>,&之類的字符的字符串,而不用將它們解釋為標記,例如:
<![CDATA[<&>是很常用的]]>。但是這里的字符串是不能包含]]>的,這也可以理解。
- 處理指令
處理指令是那么專門用來處理XML文檔的應用程序中使用的指令,它們將用<? 和 ?>來限定其界限。例如:
<?xml version="1.0"?>
- 注釋
注釋是用<!--? -->限定的文本,例如:
<!-- This is a comment -->
另外,注釋中是不能包含--的。注釋只能用來給讀者提供信息,其中絕對不能包含隱藏的命令,命令應該是用處理指令來實現的。
?
二、文檔類型定義 DTD
前面提到XML的標記不是語言事先規定的,作者可以自己來定義標記,但是這樣也出現了問題,就是別人如何理解自定義的標記,更主要的是在別人修改的時候,如何遵守原始作者的定義。
從另一個角度來看,我們將XML看作一種輕量級的數據庫使用,數據庫操作事實上存在兩個階段,數據定義階段和數據操作階段,在數據操作前,通常要定義表的結構,以便數據可以按照設定有條不紊的存放。
那么,DTD就是數據類型定義(Document Type Definition)文件,DTD文件用于說明特定XML文件的規則。DTD并不是強類型定義語言,在DTD中只有兩個數據類型#PCDATA和EMPTY,有數據和沒有數據,對于XML的主要應用方向之一的配置文件,這樣設計DTD無可厚非,因為配置文件對數據類型并沒有太多的要求。
然而,在某些情況下,當我們需要更精確的數據類型定義的時候,DTD就顯得束手無策了,比如我們定義的元素性別,我們希望其數據類型為男/女,這個時候DTD就無法實現,只能簡單的設置成#PCDATA。
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT 學校 (學生+)>
<!ELEMENT 學生 (姓名,性別)>
<!ELEMENT 姓名 (#PCDATA)>
<!ELEMENT 性別 (#PCDATA)>
在XML文件中使用<!DOCTYPE>來將XML文件和DTD文件進行綁定,只能是大寫字母,后面是根元素標記名字。SYSTEM表示DTD在文件系統中,如果是PUBLIC則表示將使用互聯網上的DTD,此時除了地址還需要額外指定DTD的名字。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE 學校 SYSTEM "?C:\school.dtd">
<學校><學生><姓名>張三</姓名><性別>男</性別>
</學校>
?
三、Schema
Schema是DTD的替代品,它的作用也是來約束XML文件的,XML Schema 語言也稱作 XML Schema 定義(XML Schema Definition,XSD)。
那么既然有了DTD為什么還需要Schema呢,我們認為 XML Schema 很快會在大部分網絡應用程序中取代 DTD。理由如下:
- XML Schema 可針對未來的需求進行擴展
- XML Schema 更完善,功能更強大
- XML Schema 基于 XML 編寫
- XML Schema 支持數據類型
- XML Schema 支持命名空間
Schema本身也是基于XML編寫的,可使用 XML 編輯器來編輯 Schema 文件,使用 XML 解析器來解析 Schema 文件,并且通過 XML DOM 來處理 Schema。
一個簡單的 XML 文檔:
請看這個名為 "note.xml" 的 XML 文檔:
<?xml version="1.0"?>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
XML Schema
下面這個例子是一個名為 "note.xsd" 的 XML Schema 文件,它定義了上面那個 XML 文檔( "note.xml" )的元素:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.w3schools.com"
xmlns="http://www.w3schools.com"
elementFormDefault="qualified"><xs:element name="note"><xs:complexType><xs:sequence><xs:element name="to" type="xs:string"/><xs:element name="from" type="xs:string"/><xs:element name="heading" type="xs:string"/><xs:element name="body" type="xs:string"/></xs:sequence></xs:complexType>
</xs:element></xs:schema>
首先,需要注意的是Schema也是個XML文件,所以它也有自己的命名空間。
<?xml version="1.0"?><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.w3school.com.cn"
xmlns="http://www.w3school.com.cn"
elementFormDefault="qualified">...
...
</xs:schema>
其中,下面這句表示給這個XML中Schema定義了一個命名空間http://www.w3.org/2001/XMLSchema
,xs為使用時的前綴。
xmlns:xs="http://www.w3.org/2001/XMLSchema"
顯示被此 Schema 定義的元素 (note, to, from, heading, body) 來自命名空間: "http://www.w3school.com.cn"
,即這個schema是為”http://www.w3school.com.cn“命名空間所提供約束的,也就是被聲明為http://www.w3school.com.cn命名空間的xml文件所引用。
targetNamespace="http://www.w3school.com.cn"
下面是用來指出 Schema 中元素的默認的命名空間是 "http://www.w3school.com.cn"
。
xmlns="http://www.w3school.com.cn"
?
四、命名空間
有時在一個團隊中,不同任務的人都需要使用XML,各自設計約束難免會有元素重復的問題,使用命名空間就是用來解決這個問題的。
XML 命名空間屬性被放置于元素的開始標簽之中,并使用以下的語法,用于標示命名空間的地址不會被解析器用于查找信息。其惟一的作用是賦予命名空間一個惟一的名稱。一個元素可以有多個命名空間,里面帶前綴的是特地的命名空間,不帶前綴的是默認命名空間。
xmlns:namespace-prefix="namespaceURI"
當命名空間被定義在元素的開始標簽中時,所有帶有相同前綴的子元素都會與同一個命名空間相關聯。
很多公司使用URL作為命名空間名稱,這是因為這里的URL肯定是唯一的,其實這個道理和Java包名的命名為反向域名是同一個道理。
XML 中對 Schema 的引用
此文件包含對 XML Schema 的引用:
<?xml version="1.0"?>
<note
xmlns="http://www.w3school.com.cn"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3school.com.cn note.xsd"><to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
在根元素中指定了默認命名空間為http://www.w3school.com.cn
。
xmlns="http://www.w3school.com.cn"
又定義了一個命名空間xsi(官方叫XML Schema 實例命名空間)。定義這個命名空間的原因是,schemaLocation 屬性在這個命名空間下,也就是說,只有先定義了這個命名空間,才能使用schemaLocation 屬性。上文已經提到了,命名空間的URI是只是作為區分字符串使用的,并不包含真正的XSD文件,真正的XSD文件的位置需要通過xsi下的schemaLocation屬性進行定義。
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
設置xsi前綴代表的命名空間中的一個屬性schemaLocation為"http://www.w3school.com.cn note.xsd"。
XML Schema 實例命名空間下的schemaLocation屬性,實際語法其實是, xsi:schemaLocation = "key" "value"。
也就是說
xsi 命名空間下 schemaLocation 元素的值為一個由空格分開的鍵值對。前一個“鍵” http://www.w3school.com.cn
指代 namespace, 只是一個全局唯一字符串而已。后一個值指代 【XSD location URI】 , 這個值指示了前一個命名空間所對應的 XSD 文件的位置, xml parser 可以利用這個信息獲取到 XSD 文件, 從而通過 XSD 文件對所有屬于命名空間??http://www.w3school.com.cn
的元素結構進行校驗, 因此這個值必然是可以訪問的, 且訪問到的內容是一個 XSD 文件的內容。
xsi:schemaLocation="http://www.w3school.com.cn note.xsd"
?
五、XML文件設計
- 在設計XML的時候,應該盡量使元素要么包含子元素,要么包含文本。換句話說,你應該避免以下的情況:
<font>Java<size>36</size>
</font>
在XML規范里,這叫做混合式內容(mixed content)。如果包含混合式的內容那么在樹形遍歷子節點的時候就會出現需要進行判別的情況。所以要避免混合式內容,這樣可以簡化解析的過程。
- 何時使用元素,何時使用屬性
這個問題在XML設計人員中存在著分歧。例如將font做如下的描述:
<font name="Java" size="36"/>
似乎要比下面的更簡單一些:
<font><name>Java</name><size>36</size></font>
但是屬性的靈活性要差很多,假設你想把單位添加到size中去。如果使用屬性,那么必須把單位添加到屬性值中去:
<font name="Java" size="36 pt">
o no!這時候就需要對字符串“36 pt”進行解析,而這正是XML設計用來避免的麻煩。但是,如果把屬性加到size元素中就會非常的方便:
<font><name>Java</name><size unit="pt">36</size></font>
一個常用的經驗法則是,屬性值應該用來修改值的解釋,而不是用來指定值。在HTML中屬性的使用規范很簡單:凡是不顯示在網頁上的都是屬性。
?
六、XML解析
用程序讀寫XML,要說這不該是問題,因為大多數編程語言都有IO流的支持,但是深入的看就會發現,寫XML用IO流相對容易,可以讀取卻并不那么容易,因為我們的需求往往不僅僅要有讀取文件內容的能力,在大多數情況下,我們需要獲取某一個特定元素的值,如果單純依賴IO流,每次都需要寫比較復雜的分析程序,而這些代碼完全可以復用。
因此W3C提出了一個統一的標準DOM,文檔對象模型(Document Object Model,簡稱DOM)。DOM的思想是將XML文件讀到內存中,使其形成一個對象,這個對象內在映射著XML文件的樹形結構,我們可以通過調用對象的成員方法來訪問這些內容。
W3C做這件事還有一個巨大的好處,DOM不是建立在某個編程語言的基礎上的,作為一個國際標準,幾乎所有的編程語言都實現了這個標準,這樣不同的語言利用DOM訪問XML的做法就基本一致了。
XML技術的有趣之處在于總是有兩個相同功能的不同技術,比如DTD和Schema、CSS和XSL,現在是DOM和SAX,DOM和SAX的功能一樣,都是用來解析XML文件的,不同之處在于DOM一次性將整個XML文件讀入到內存中,并且包裝成對象,而SAX每次只讀取一行,處理完后將這一行拋棄然后處理下一行,這樣做的好處是不占用太多的內存,如果XML作為數據庫應用,那么有可能內容過多,文件很大,使用DOM或許會超出內存的大小,這時就只能使用SAX,但是這樣也說明SAX應用不如DOM頻繁,因為讀取很大的XML文件的機會并不多,SAX的另外一個缺點就是,因為數據會被丟棄,所以和DOM相比無法再次使用數據。
?