XML 指可擴展標記語言。標記指計算機所能理解的信息符號,通過此種標記,計算機之間可以處理包含各種信息的文章等。
XML 廣泛應用于數據的存儲與傳輸。
簡介
什么是 XML
- XML,即可擴展標記語言(eXtensible Markup Language )。
- XML 的設計宗旨是傳輸數據,而不是顯示數據。
- XML 標簽沒有被預定義。需要使用者自行定義標簽。
- XML 具有自我描述性。
XML 與 HTML 之間的差異
XML 和 HTML 為不同的目的而設計:
- XML 被設計用來傳輸和存儲數據,其焦點是數據的內容。
- HTML 被設計用來顯示數據,其焦點是數據的外觀。
HTML 旨在顯示信息,而 XML 旨在傳輸信息。
對 XML 最好的描述是:XML 是獨立于軟件和硬件的信息傳輸工具。
XML 不會做任何事情
下面的示例是 Jenny 寫給 Tom 的便簽,存儲為 XML:
<note>
<to>Tom</to>
<from>Jenny</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
上面這條便簽(<note>
)具有自我描述性。它包含了發送者(<from>
)和接收者(<to>
)的信息,同時擁有標題(<heading>
)以及消息主體(<body>
)。
但是,這個 XML 文檔仍然沒有做任何事情。它僅僅是包裝在 XML 標簽中的純粹的信息。我們需要編寫軟件或者程序,才能傳送、接收和顯示出這個文檔。
通過 XML 可以自定義標簽
上面示例中的標簽沒有在任何 XML 標準中定義過(比如 <to>
和 <from>
)。這些標簽是由 XML 文檔的創作者發明的。
這是因為 XML 語言沒有預定義的標簽。
HTML 中使用的標簽都是預定義的。HTML 文檔只能使用在 HTML 標準中定義過的標簽(如 <p>
、<h1>
等等)。
XML 允許創作者定義自己的標簽和自己的文檔結構。
用途
XML 把數據從 HTML 分離
如果需要在 HTML 文檔中顯示動態數據,那么每當數據改變時將花費大量的時間來編輯 HTML。
通過 XML,數據能夠存儲在獨立的 XML 文件中。這樣就可以專注于使用 HTML/CSS 進行顯示和布局,并確保修改底層數據不再需要對 HTML 進行任何的改變。
通過使用幾行 JavaScript 代碼,就可以讀取一個外部 XML 文件,并更新網頁的數據內容。
XML 簡化數據傳輸與共享
在真實的世界中,計算機系統和數據使用不兼容的格式來存儲數據。
XML 數據以純文本格式進行存儲,因此提供了一種獨立于軟件和硬件的數據存儲方法。
這讓創建不同應用程序可以共享的數據變得更加容易。
XML 用于創建新的互聯網語言
很多新的互聯網語言是通過 XML 創建的。
這里有一些示例:
- XHTML
- 用于描述可用的 Web 服務 的 WSDL
- 作為手持設備的標記語言的 WAP 和 WML
- 用于新聞 feed 的 RSS 語言
- 描述資本和本體的 RDF 和 OWL
- 用于描述針對 Web 的多媒體 的 SMIL
樹結構
XML 文檔形成了一種樹結構,它從“根部”開始,然后擴展到“枝葉”。
樹結構通常稱作 XML 樹,可以很容易地描述任何 XML 文檔。
通過采用樹狀結構,可以知道所有從根開始的后續的分行及支行。
舉例說明
XML 文檔使用簡單的具有自我描述性的語法:
<?xml version="1.0" encoding="utf-8"?>
<note>
<to>Tom</to>
<from>Jenny</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
第一行是 XML 聲明。它定義 XML 的版本(1.0)和所使用的編碼(UTF-8)。
下一行描述文檔的根元素(像在說:“本文檔是一個便簽”):
<note>
接下來四行描述根的 4 個子元素(to、from、heading 和 body):
<to>Tom</to>
<from>Jenny</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
最后一行定義根元素的結尾:
</note>
可以假設,從這個示例中,XML 文檔包含了一張 Jenny 寫給 Tom 的便簽。
XML 文檔形成一種樹結構
XML 文檔必須包含根元素。該元素是所有其他元素的父元素。
XML 文檔中的元素形成了一棵文檔樹。這棵樹從根部開始,并擴展到樹的最底端。
所有的元素都可以有子元素:
<root>
<child>
<subchild>…</subchild>
</child>
</root>
父、子以及同胞等術語用于描述元素之間的關系。父元素擁有子元素。相同層級上的子元素成為同胞(兄弟或姐妹)。
所有的元素都可以有文本內容和屬性(類似 HTML 中)。
示例
上圖表示下面的 XML 中的一本書:
<bookstore>
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="CHILDREN">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="WEB">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
示例中的根元素是 <bookstore>
。文檔中的所有 <book>
元素都被包含在 <bookstore>
中。
<book>
元素有 4 個子元素:<title>
、<author>
、<year>
、<price>
。
語法
所有的 XML 元素都必須有一個關閉標簽
在 HTML 中,某些元素不必有一個關閉標簽:
<p>This is a paragraph.
<br>
在 XML 中,省略關閉標簽是非法的。所有元素都必須有關閉標簽:
<?xml version="1.0" encoding="UTF-8" ?>
<p>This is a paragraph.</p>
在上面的示例中,注意到 XML 第一行中聲明沒有關閉標簽。這不是錯誤。聲明不是 XML 文檔本身的一部分,它沒有關閉標簽。
XML 標簽對大小寫敏感
XML 標簽對大小寫敏感。標簽 <Message>
與 <message>
是不同的。
必須使用相同的大小寫來編寫打開標簽和關閉標簽:
<Message>This is incorrect</message>
<message>This is correct</message>
打開標簽和關閉標簽通常稱為開始標簽和結束標簽。
XML 必須正確嵌套
在 HTML 中,常會看到沒有正確嵌套的元素:
<b><i>This text is bold and italic</b></i>
在 XML 中,所有元素都必須彼此正確地嵌套:
<b><i>This text is bold and italic</i></b>
在上面的示例中,正確嵌套的意思是:由于 <i>
元素是在 <b>
元素內打開的,那么它必須在 <b>
元素內關閉。
XML 文檔必須有根元素
XML 文檔必須有一個元素是所有其他元素的父元素。該元素稱為根元素。
<root>
<child>
<subchild>…</subchild>
</child>
</root>
XML 屬性值必須加引號
與 HTML 類似,XML 元素也可擁有屬性(名稱/值的對)。
在 XML 中,屬性值必須加引號。
<note date=12/11/2007>
<to>Tom</to>
<from>Jenny</from>
</note>
實體引用
在 XML 中,一些字符擁有特殊的意義。
如果把字符 <
放在 XML 元素中,會發生錯誤,這是因為解析器會把它當作新元素的開始:
<message>if salary < 1000 then</message>
為了避免這個錯誤,用實體引用來代替 <
字符:
<message>if salary < 1000 then</message>
在 XML 中,有 5 個預定義的實體引用:
預定義實體引用 | 符號 | 意義 |
---|---|---|
< |
< | 小于 |
> |
> | 大于 |
& |
& | 表示“and” |
' |
' | 單引號 |
" |
" | 雙引號 |
在 XML 中,只有字符
<
和&
確實是非法的。大于號是合法的,但是用實體引用來代替它是一個好習慣。
XML 中的注釋
在 XML 中編寫注釋的語法與 HTML 的語法很相似。
<!-- This is a comment -->
在 XML 中,空格會被保留
HTML 會把多個連續的空格字符裁減(合并)為一個:
HTML: | Hello Tom |
---|---|
輸出: | Hello Tom |
在 XML 中,文檔中的空格不會被刪減。
XML 以 LF 存儲換行
在 Windows 應用程序中,換行通常以一對字符來存儲——回車符(CR)和換行符(LF),即回車換行符(CRLF)。
在 UNIX、Linux、macOS 中,使用 LF 來存儲新行。
XML 以 LF 存儲換行。
元素
什么是 XML 元素
XML 元素指的是從(且包括)開始標簽直到(且包括)結束標簽的部分。
一個元素可以包含:
- 其他元素
- 文本
- 屬性
- 或混合以上所有……
<bookstore>
<book category="CHILDREN">
<title>Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="WEB">
<title>Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
在上面的示例中,<bookstore>
和 <book>
都有 元素內容,因為它們包含其他元素。<book>
元素也有屬性(category="CHILDREN"
)。<title>
、<author>
、<year>
和 <price>
有文本內容,因為它們包含文本。
XML 命名規則
XML 元素必須遵循以下命名規則:
- 名稱可以包含字母、數字以及其它的字符。
- 名稱不能以數字或者標點符號開始。
- 名稱不能以字母 xml(或者 XML、Xml 等等)開始。
- 名稱不能包含空格。
可使用任何名稱,沒有保留的字詞。
最佳命名習慣
使名稱具有描述性。使用下劃線的名稱也很不錯:<first_name>
、<last_name>
。
名稱應簡短和簡單,比如 <book_title>
,而不是 <the_title_of_the_book>
。
- 避免
-
字符。如果按照這樣的方式進行命名:“first-name”,一些軟件會認為想要從 first 里邊減去 name。 - 避免
.
字符。如果按照這樣的方式進行命名:“first.name”,一些軟件會認為“name”是對象“first”的屬性。 - 避免
:
字符。冒號會被轉換為命名空間來使用(稍后介紹)。
XML 文檔經常有一個對應的數據庫,其中的字段會對應 XML 文檔中的元素。有一個實用的經驗——使用數據庫的命名規則來命名 XML 文檔中的元素。
在 XML 中,éòá 等非拉丁字母是完全合法的,不過需要留意軟件供應商不支持這些字符時可能出現的問題。
XML 元素是可擴展的
XML 元素是可擴展,以攜帶更多的信息。
XML 的優勢之一,就是可以在不中斷應用程序的情況下進行擴展。
在現有 XML 文檔中添加新的內容而不改動原有的內容時,不會對當前正在使用該 XML 文檔的應用程序產生影響。
XML 屬性
屬性是 XML 元素的一部分。一個元素可以有多個獨特的屬性。屬性提供了有關 XML 元素的詳細信息。
什么是屬性
XML 屬性始終是一個名稱-值的對。
在 HTML 中,屬性提供有關元素的額外信息:
<img src="computer.gif">
<a href="demo.html">
屬性通常提供不屬于數據組成部分的信息。在下面的示例中,文件類型與數據無關,但是對需要處理這個元素的軟件來說卻很重要:
<file type="gif">computer.gif</file>
XML 屬性必須加引號
屬性值必須被引號包圍,不過單引號和雙引號均可使用。比如一個人的性別,person
元素可以這樣寫:
<person sex="female">
或者這樣:
<person sex='female'>
如果屬性值本身包含雙引號,可以使用單引號:
<gangster name='George "Shotgun" Ziegler'>
XML 元素 VS. 屬性
<person sex="female">
<firstname>Anna</firstname>
<lastname>Smith</lastname>
</person>
<person>
<sex>female</sex>
<firstname>Anna</firstname>
<lastname>Smith</lastname>
</person>
在第一個示例中,sex
是一個屬性。在第二個示例中,sex
是一個元素。這兩個示例都提供相同的信息。
沒有什么規矩可以告訴我們什么時候該使用屬性,而什么時候該使用元素。在 HTML 中,屬性用起來很便利,但是在 XML 中,應該盡量避免使用屬性。如果信息感覺起來很像數據,那么請使用元素吧。
避免 XML 屬性?
因使用屬性而引起的一些問題:
- 屬性不能包含多個值(元素可以)
- 屬性不能包含樹結構(元素可以)
- 屬性不容易擴展(為未來的變化)
屬性難以閱讀和維護。請盡量使用元素來描述數據。而僅僅使用屬性來提供與數據無關的信息。
下面是一個過度使用屬性的極端的例子。應注意避免,這不是使用 XML 的應該的方式:
<note day="10" month="01" year="2008"
to="Tove" from="Jani" heading="Reminder"
body="Don't forget me this weekend!">
</note>
針對元數據的 XML 屬性
有時候會向元素分配 ID 引用。這些 ID 索引可用于標識 XML 元素,它起作用的方式與 HTML 中 id 屬性是一樣的。這個示例向我們演示了這種情況:
<messages>
<note id="501">
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
<note id="502">
<to>Jani</to>
<from>Tove</from>
<heading>Re: Reminder</heading>
<body>I will not</body>
</note>
</messages>
上面的 id 屬性僅僅是一個標識符,用于標識不同的便簽。它并不是便簽數據的組成部分。
在此我們極力向您傳遞的理念是:元數據(有關數據的數據)應當存儲為屬性,而數據本身應當存儲為元素。
規則總結
以下是總結性的 XML 屬性需要遵循的規則:
- 屬性名稱不能在同一起始標簽或空元素標簽中出現一次。
- 一個屬性必須使用屬性表聲明的文檔類型定義(DTD)的聲明。
- 屬性值不能包含直接或間接的實體引用外部實體。
- 任何實體的替換文本稱為直接或間接的屬性值中不能包含任何小于號。
文檔類型定義
文檔類型定義(Document Type Definition ),簡稱 DTD。
XML 驗證
擁有正確語法的 XML 被稱為“形式良好”的 XML。
通過 DTD 驗證的XML是“合法”的 XML。
形式良好的 XML 文檔
“形式良好”的 XML 文檔擁有正確的語法。
在前面的章節描述的語法規則:
- XML 文檔必須有一個根元素。
- XML 元素都必須有一個關閉標簽。
- XML 標簽對大小寫敏感。
- XML 元素必須被正確地嵌套。
- XML 屬性值必須加引號。
驗證 XML 文檔
合法的 XML 文檔是“形式良好”的 XML 文檔,這符合 DTD 的規則。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note SYSTEM "Note.dtd">
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
在上面的示例中,DOCTYPE
聲明是對外部 DTD 文件的引用。下面的段落展示了這個文件的內容。
XML DTD
DTD 的目的是定義 XML 文檔的結構。它使用一系列合法的元素來定義文檔結構:
<!DOCTYPE note
[
<!ELEMENT note (to, from, heading, body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
XML Schema
W3C 支持一種基于 XML 的 DTD 替代者,它名為 XML Schema:
<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>
命名空間
命名空間是一組唯一的名稱,該命名空間是確定的 URI(統一資源標識符)。
命名沖突
在 XML 中,元素名稱是由開發者定義的。當兩個不同的文檔使用相同的元素名時,就會發生命名沖突。
這個 XML 攜帶 HTML 表格的信息:
<table>
<tr>
<td>Apples</td>
<td>Bananas</td>
</tr>
</table>
這個 XML 文檔攜帶有關桌子的信息(一件家具):
<table>
<name>African Coffee Table</name>
<width>80</width>
<length>120</length>
</table>
假如這兩個 XML 文檔被一起使用,由于兩個文檔都包含帶有不同內容和定義的 <table>
元素,就會發生命名沖突。
XML 解析器無法確定如何處理這類沖突。
使用前綴來避免命名沖突
在 XML 中的命名沖突可以通過使用名稱前綴從而容易地避免。
該 XML 攜帶某個 HTML 表格和某件家具的信息:
<h:table>
<h:tr>
<h:td>Apples</h:td>
<h:td>Bananas</h:td>
</h:tr>
</h:table>
<f:table>
<f:name>African Coffee Table</f:name>
<f:width>80</f:width>
<f:length>120</f:length>
</f:table>
在上面的示例中,不會有沖突,因為兩個 <table>
元素有不同的名稱。
xmlns 屬性
當在 XML 中使用前綴時,一個所謂的用于前綴的命名空間必須被定義。
命名空間是在元素的開始標簽的 xmlns 屬性中定義的。
命名空間聲明的語法如下:
xmlns:前綴="URI"
<root>
<h:table xmlns:h="http://www.w3.org/TR/html4/">
<h:tr>
<h:td>Apples</h:td>
<h:td>Bananas</h:td>
</h:tr>
</h:table>
<f:table xmlns:f="http://www.w3cschool.cn/furniture">
<f:name>African Coffee Table</f:name>
<f:width>80</f:width>
<f:length>120</f:length>
</f:table>
</root>
在上面的示例中,<table>
標簽的 xmlns
屬性定義了 h:
和 f:
前綴的合格命名空間。
當命名空間被定義在元素的開始標簽中時,所有帶有相同前綴的子元素都會與同一個命名空間相關聯。
命名空間可以在使用它們的元素中或者在根元素中聲明:
<root xmlns:h="http://www.w3.org/TR/html4/"
xmlns:f="http://www.w3cschool.cn/furniture">
<h:table>
<h:tr>
<h:td>Apples</h:td>
<h:td>Bananas</h:td>
</h:tr>
</h:table>
<f:table>
<f:name>African Coffee Table</f:name>
<f:width>80</f:width>
<f:length>120</f:length>
</f:table>
</root>
命名空間 URI 不會被解析器用于查找信息。
其目的是賦予命名空間一個唯一的名稱。不過,很多公司常常會作為指針來使用命名空間指向實際存在的網頁,這個網頁包含關于命名空間的信息。
默認的命名空間
為元素定義默認的命名空間可以讓我們省去在所有的子元素中使用前綴的工作。語法如下:
xmlns="namespaceURI"
這個 XML 攜帶 HTML 表格的信息:
<table xmlns="http://www.w3.org/TR/html4/">
<tr>
<td>Apples</td>
<td>Bananas</td>
</tr>
</table>
這個 XML 攜帶有關一件家具的信息:
<table xmlns="http://www.w3cschool.cn/furniture">
<name>African Coffee Table</name>
<width>80</width>
<length>120</length>
</table>
CDATA
CDATA 指字符數據,我們將其定義為文本塊。
XML 文檔中的所有文本均會被解析器解析。只有 CDATA 區段中的文本會被解析器忽略。
PCDATA——被解析的字符數據
XML 解析器通常會解析 XML 文檔中所有的文本。
當某個 XML 元素被解析時,其標簽之間的文本也會被解析:
<message>This text is also parsed</message>
解析器之所以這么做是因為 XML 元素可包含其他元素,就像這個示例中,其中的 <name>
元素包含著另外的兩個元素(first
和 last
):
<name><first>Bill</first><last>Gates</last></name>
而解析器會把它分解為像這樣的子元素:
<name>
<first>Bill</first>
<last>Gates</last>
</name>
解析字符數據(PCDATA)是 XML 解析器解析的文本數據使用的一個術語。
CDATA——(未解析)字符數據
術語 CDATA 指的是不應該由 XML 解析器解析的文本數據。
像 <
和 &
字符在 XML 元素中都是非法的:
-
<
會產生錯誤,因為解析器會把該字符解釋為新元素的開始。 -
&
會產生錯誤,因為解析器會把該字符解釋為字符實體的開始。
某些文本,比如 JavaScript 代碼,包含大量 <
或 &
字符。為了避免錯誤,可以將腳本代碼定義為 CDATA。
CDATA 部分中的所有內容都會被解析器忽略。
CDATA 部分由“<![CDATA[
”開始,由“]]>
”結束:
<script>
<![CDATA[
function matchwo(a, b)
{
if (a < b && a < 0) then
{
return 1;
}
else
{
return 0;
}
}
]]>
</script>
在上面的示例中,解析器會忽略 CDATA 部分中的所有內容。
CDATA 部分不能包含字符串“]]>
”。也不允許嵌套的 CDATA 部分。
標記 CDATA 部分結尾的“]]>
”不能包含空格或換行。
服務器上的 XML
如果想要讓瀏覽器能夠訪問 Web 項目,那么需要配置服務器里面的 web.xml
文件。一旦配置不成功,瀏覽器就無法進行訪問。
XML 能夠通過標準的 Web 服務器輕松地存儲和生成。
通過 ASP 生成 XML
XML 可在不安裝任何 XML 軟件的情況下在服務器端生成。
如需從服務器生成 XML 響應,只需簡單地編寫以下代碼并在 Web 服務器上把它保存為一個 ASP 文件:
<%
response.ContentType="text/xml"
response.Write("<?xml version='1.0' encoding='utf-8'?>")
response.Write("<note>")
response.Write("<from>Jani</from>")
response.Write("<to>Tove</to>")
response.Write("<message>Remember me this weekend</message>")
response.Write("</note>")
%>
請注意,此響應的內容類型必須設置為“text/xml”。
從 Access 數據庫生成 XML
XML 可在不安裝任何 XML 軟件的情況下從數據庫生成。
如需從服務器生成 XML 數據庫響應,只需簡單地編寫以下代碼,并把它在 Web 服務器上保存為 ASP 文件:
<%
response.ContentType = "text/xml"
set conn=Server.CreateObject("ADODB.Connection")
conn.provider="Microsoft.Jet.OLEDB.4.0;"
conn.open server.mappath("/db/database.mdb")
sql="select fname,lname from tblGuestBook"
set rs=Conn.Execute(sql)
response.write("<?xml version='1.0' encoding='utf-8'?>")
response.write("<guestbook>")
while (not rs.EOF)
response.write("<guest>")
response.write("<fname>" & rs("fname") & "</fname>")
response.write("<lname>" & rs("lname") & "</lname>")
response.write("</guest>")
rs.MoveNext()
wend
rs.close()
conn.close()
response.write("</guestbook>")
%>
上面的示例使用了帶有 ADO 的 ASP。