既然是速成,那就用最簡單粗暴的方式介紹知識。
目錄
1. Why XML
2. How XML
2.1 Text With Marks
2.2 Come on, XML
2.2.1 序言
2.2.2 注釋
2.2.3 元素
2.2.4 例子
3. Exercise
1. Why XML
首先是XML文件的介紹。首先,我們看一個文本文件:
Moyun Li 25 100 false false Fulei Xie 25 0 false true Ke Lin 38 5 true false
這個文本文件表達了什么含義呢?很明顯,這是三條個人信息,并表達了三條記錄,分別表示三個叫Moyun Li,Fulei Xie和Ke Lin的人一些信息。但是,這些信息究竟是什么意思呢?從數據本身來說,我們無法得知究竟這些數據是什么含義。
或許我們可以為這個文本文件在給出一個描述文件。這個描述文件用來標識這些數據的含義。例如:
名字 姓氏 年齡 談戀愛的次數:) 是否結婚 是否是...俗稱“處男”
這樣,我們就可以從解讀出上面的數據,得知Moyun Li是一個花花公子,而Fulei Xie是一個沒人要的死宅男。
但是,這樣寫有一個壞處,那就是我們得有兩個文件:一個文件是數據文件,另一個文件是對數據的描述文件。這樣,我們就把“數據”和“描述”分離開了。
數據和描述相分離不是不可以,但是同樣帶來了一些問題。
第一個問題是,容易出錯。例如,對于每一條記錄的最后兩項,表達的格式分別是true/false。如果程序員不小心,或者保存數據的人不小心,非常容易把記錄弄顛倒。
第二個問題是,難以擴展。例如,對于已婚人士,我們希望增加一條信息:是否有小孩。但如果需要增加這一條信息的話,必須要修改“描述”文件,增加這么一個數據項;同時更新所有數據記錄。這樣,我們的數據描述文件就要變為:
名字 姓氏 年齡 談戀愛的次數:) 是否結婚 小孩的個數 是否是...俗稱“處男”
同時,所有的數據文件都要改:
Moyun Li 25 100 false 0 false Fulei Xie 25 0 false 0 true Ke Lin 38 5 true 1 false
我們可以看到,一旦修改數據描述文件,那么牽一發而動全身,不但Kevin這條記錄要修改,所有的記錄都必須要修改。
正因為數據和描述分離會產生這樣或那樣的問題,因此我們引入XML,來看看XML是怎樣解決問題的。
2. How XML
2.1 Text with Marks
我們用另一種方式來描述我們之前提到的幾條記錄。我們為數據加上一些尖括號,在尖括號里面加上對數據的描述。同時,<XXX> 表示數據開始,</XXX>表示數據結束。則結果如下:
<Staff> <FirstName>Moyun</FirstName> <LastName>Li</LastName> <Age>25</Age> <Lovers>100</Lovers> <Married>false</Married> <Virgin>false</Virgin> </Staff> <Staff> <FirstName>Fulei</FirstName> <LastName>Xie</LastName> <Age>25</Age> <Lovers>0</Lovers> <Married>false</Married> <Virgin>true</Virgin> </Staff>
<Staff> <FirstName>Kevin</FirstName> <LastName>Lin</LastName> <Age>38</Age> <Lovers>5</Lovers> <Married>true</Married> <Virgin>false</Virgin> </Staff>
首先,我們可以看到,為了區分三條不同的記錄,我們為每一條記錄的開始增加了一個標簽<Staff>,為每一條記錄的結束增加了一個標簽</Staff>。這樣,我們通過這種方式,非常清楚的區分了這三條記錄。
而在Staff內部,則是每一條記錄的數據。我們分別定義了FirstName,LastName,Age,Lovers,Married以及Virgin這樣幾個標簽,分別用來描述數據的含義。
這樣,我們就把數據,以及對數據的描述結合在一起了。這種情況下,我們就比較好的解決了“數據”和“描述”相分離的問題,并比較好的解決了“易出錯”和“難以擴展”這兩個問題。接下來我們來解釋一下,這種帶標簽的文本是如何解決這兩個問題的。
首先,“易出錯”的問題。對于原來的數據來說,如果我們把Fulei Xie這條記錄的最后兩項顛倒一下:
Fulei Xie
25
0
true
false
這樣一來,整個數據的含義都發生了改變。
但是,如果我們把帶標簽的Fulei Xie最后兩條進行顛倒:
<Staff> <FirstName>Fulei</FirstName> <LastName>Xie</LastName> <Age>25</Age> <Lovers>0</Lovers> <Virgin>true</Virgin> <Married>false</Married> </Staff>
雖然最后的值變成了true / false,但是實際上表示起來沒有任何歧義。因為數據和數據的描述緊密的結合在一起,這樣在解釋數據的時候,就能夠避免很多錯誤。
其次,我們來看看帶標簽的文本是如何解決擴展性的問題。我們修改“Kevin Lin”這條記錄:
<Staff> <FirstName>Kevin</FirstName> <LastName>Lin</LastName> <Age>38</Age> <Lovers>5</Lovers> <Married>true</Married> <Kids>1</Kids> <Virgin>false</Virgin> </Staff>
這樣,我們很輕松的為Kevin Lin增加了Kids這個新的字段。同時,為Kevin增加Kids這個描述的同時,對Fulei Xie以及Moyun Li這兩條記錄的理解完全沒有影響。
2.2 Come on, XML
XML的意思是可擴展標記語言(eXtensible Markup Language,簡稱XML),在我看來,其基本思想就是帶標簽的文本,并且把數據以及對數據的描述結合起來。
XML文件的通常有以下幾部分組成:
2.2.1 序言
序言看起來的樣子往往是這樣的:
<?xml version="1.0" encoding="UTF-8" ?>
這里面指定了xml的版本是1.0,并指定XML文件編碼方式是UTF-8。
通常,有編碼方式,就意味著中文顯示會有麻煩。而中文顯示的麻煩,又來源于大陸和臺灣、香港的不統一。這是一個中國程序員心中永遠的痛……算了,不提他了,以后我的XML里面,都用英文吧……
序言通常來說格式固定。關于序言的更多內容,那個……自個兒上網搜吧。速成不教這個。
2.2.2 注釋
在xml文件中,可以加注釋。注釋的格式是:
<!--這里是注釋-->
而且注釋可以跨越多個換行符,也就是說,可以給XML文件增加多行注釋,例如:
<!--多行注釋
的例子—>
2.2.3 元素
所謂的元素,是英文"Element"的翻譯。通常,一個元素由這樣幾部分組成:
a) Start-Tag & End Tag
b) Content
c) Attribute
我們一一介紹。
a. Start-Tag & End Tag
Start Tag和End Tag表示開始標記和結束標記,通常的格式是:<xxx>和</xxx>。
在這兒要注意兩點:
1、xml區分大小寫。也就是說,<test></test>能夠組成一對開始和結束標記;而<test></Test>無法組成一對標記。
2、必須要正確的關閉xml標記。也就是說,一方面,有了開始標記,必須有對應的結束標記。另一方面,xml元素之間不允許交錯。例如:
<a>xxx<b>yyy</a>zzz</b>
這樣在xml中是不允許的。上面這個例子中,a標記的開始和結束,與b標記的開始和結束產生了交錯。而下面的例子:
<a>xxx<b>yyy</b>zzz</a>
是允許的。在這種情況下,a元素包含b元素。
除了開始標記和結束標記之外,還有一種標記。例如:
<singleelement/>
這表示這是一個單獨的元素,這個元素不包含任何內容。不包含任何內容的元素有用么?有用。一方面,元素不包含內容,但是元素可以包含“屬性”。這個屬性,就是我們后面會提到的Attribute。另一方面,這個元素可能僅僅用來標識一個很簡單的意義。例如,在網頁中,可以用<br/>來表示一個回車。這個<br/>就是一個單獨的元素,而不用再加上開始標記和結束標記。
b. Content
所謂的Content,指的是一個元素的內容,也就是在開始標記和結束標記之間的東西。
首先,元素可以沒有內容。例如我們剛剛提到的,<singleelement/>就是一個沒有內容的元素。
其次,元素的內容可以是純文本或者其他元素。
例如,我們來看Fulei Xie的那條記錄:
<Staff1> <FirstName>Fulei</FirstName> <LastName>Xie</LastName> </Staff1>
在這條記錄中,有FirstName這么一個元素。這個元素的開始標記和結束標記中間的內容,就是Fulei這個字符串。
需要注意的是,XML沒有int或者boolean之類的類型,所有內容都當做純文本。例如,Age元素的內容是字符串25,而Virgin元素的內容是字符串true。
然后我們來看看<Staff1>這個元素。首先要明確的是,在<Staff1>和</Staff1>之間出現的所有東西,都是Staff1元素的內容。在Staff1元素中,很顯然,包含了FirstName,LastName等一系列元素,這也就說明了,元素的內容同樣可以是元素。
除此之外,我們看看下面這個例子:
<Staff2><FirstName>Fulei</FirstName><LastName>Xie</LastName></Staff2>
這個Staff2和上面那條Staff1有什么不同么?
很顯然,在這條記錄中,少了一些回車和空格。
那么,有這么一個問題:空格和回車,算不算之前那個Staff1的內容呢?
答案很明確:算。
也就是說,Staff1的內容由五部分組成,分別是:
1) (<Staff1>后面的)回車和(<FirstName>之前)空格
2) FirstName元素
3) (</FirstName>后面的)回車和(<LastName>之前的)空格
4) LastName元素
5) (</LastName>后面的)回車
而Staff2的內容只有兩部分,分別是:
1) FirstName元素
2) LastName元素
請牢牢記住,空格和回車同樣是元素的內容。
c. Attribute
Attribute表示屬性,元素的Attribute可以這樣表示:
<element attributeName=”attributeValue”>…</element>
例如,對于之前Fulei Xie的Lovers元素,如果使用Content,則寫成:
<Lovers>0</Lovers>
我們用Attribute的方式,就可以寫成:
<Lovers number="0"></Lovers>
這樣,元素就沒有內容,就可以進一步簡寫成為:
<Lovers number="0"/>
我們為Lovers元素增加了一個屬性,屬性的名字為number,而屬性的值為0。
需要注意的是,屬性的值必須加上雙引號或者單引號,下面的寫法就是錯誤的:
<Lovers number=0/>
此外,我們可以為一個元素增加多個屬性。例如:
<Lovers tried="50" succeed="0"/>
這個元素,說明Fulei Xie在Lovers的問題上,嘗試了50次,但是成功的次數為0。(櫻木花道靈魂附體,嗯!)
d. Only one root element
重新回到Fulei Xie的例子。
<Staff1> <FirstName>Fulei</FirstName> <LastName>Xie</LastName> </Staff1>
對于這個例子來說,Staff1元素和FirstName元素,很顯然是有著某種聯系的。FirstName元素是Staff1元素的組成部分,被成為Staff1元素的子元素(child),而Staff1則被成為是FirstName的父元素(parent)。而FirstName和LastName之間則是并列的關系。
我們可以把這個例子再寫的復雜一點。
<Staff> <Name> <FirstName>Fulei</FirstName> <LastName>Xie</LastName> </Name> </Staff>
這樣,Name元素是Staff的子元素,而是FirstName和LastName的父元素。而Staff是FirstName和LastName的祖先元素。
下面我們要說的是xml的一個重要規定:在一個xml文件中,只能有一個根元素(root element)。也就是說,一個xml文件中,頂級的元素只能有一個,其他的元素必須都是這個頂級元素的子孫。
對于我們之前寫的標記文本,因為有三條記錄,因此我們寫出了三個頂級元素<Staff>。因此,事實上這段文本是不符合xml規范的。要么,我們把這三條記錄放到三個xml文件中,要么我們為Staff找一個父元素,寫成:
<Staffs> <!-- Moyun Li --> <Staff> ... </Staff> <!-- Kevin Lin --> <Staff> ... </Staff> ... </Staffs>
這樣,我們就能保證xml文件中僅包含一個根節點。
2.2.4 完整的例子
根據我們之前所說的xml文件的種種要求,下面給出一個完整的例子:
<?xml version="1.0" ?> <Staffs> <!-- Moyun Li --> <Staff> <Name> <FirstName>Moyun</FirstName> <LastName>Li</LastName> </Name> <Age>25</Age> <Lovers number="100"/> <Married>false</Married> <Virgin>false</Virgin> </Staff> <!-- Fulei Xie --> <Staff> <Name> <FirstName>Fulei</FirstName> <LastName>Xie</LastName> </Name> <Age>25</Age> <Lovers number="0"/> <Married>false</Married> <Virgin>true</Virgin> </Staff> <!-- Kevin Lin --> <Staff> <Name> <FirstName>Kevin</FirstName> <LastName>Lin</LastName> </Name> <Age>38</Age> <Lovers number="5"/> <Married>true</Married> <Virgin>false</Virgin> </Staff> </Staffs>
3. Take a break and exercise
休息一下,然后做個練習。
練習:
以2.2.4為基礎,進行如下修改:
1. 把Virgin作為Lovers的一個屬性
2. 為Married增加一個屬性'kid',Kevin的kid數為1,其他兩個人的kid均為0。
3. 增加一個Staff,基本信息如下:
名字:Wei
姓:Li
年齡:30
談戀愛的次數:8
婚否:yes
小孩數目:1
virgin :…,你猜?