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