![]() |
|
在快速創(chuàng)建 XML 文檔時(shí),一般都會(huì)傾向于創(chuàng)建基本的結(jié)構(gòu)并避開一些普通 XML 文檔需求,包括指定 XML 文檔聲明和 XML 文檔包含的數(shù)據(jù)的編碼類型。
考慮清單 1 所示的 XML 文檔。
清單 1. 未包含 XML 聲明和數(shù)據(jù)編碼類型的 XML 文檔
|
對(duì)于普通人來(lái)說(shuō),可以查看該文檔并將其識(shí)別為 XML,但是對(duì)于計(jì)算機(jī)來(lái)說(shuō),則很難作出這樣的判斷。在文件頂部添加 XML 聲明,可以使它更加明確、更容易識(shí)別。一行簡(jiǎn)單的代碼就可以說(shuō)明文檔是 XML,并且指出版本號(hào)和 XML 數(shù)據(jù)使用的字符編碼類型。例如:
<?xml version="1.0" encoding="us-ascii"?> |
編碼說(shuō)明中的內(nèi)容也應(yīng)該確保正確性。XML 解析器使用編碼確保 XML 文檔的單個(gè)字符被正確載入。例如,繼續(xù) 清單 1 中基于短語(yǔ)的示例,如果向文檔添加一個(gè)俄語(yǔ)條目,則會(huì)出現(xiàn)問(wèn)題,因?yàn)槟壳爸付ǖ木幋a不支持?jǐn)U展的字符集(使用俄語(yǔ)短語(yǔ)表示 hello 時(shí)要求使用擴(kuò)展字符集)。
指定錯(cuò)誤的編碼意味著解析器不能正確處理文檔;例如,如果將一個(gè)多字節(jié)擴(kuò)展字符讀取為一個(gè)單字節(jié)組成的序列,那么會(huì)導(dǎo)致數(shù)據(jù)的損壞和不良輸出。
![]() ![]() |
![]()
|
添加了 XML 聲明后,應(yīng)該確保使用 DTD 或 XSD 定義有效的 XML 文件的結(jié)構(gòu)。這兩種方法都允許 XML 解析器檢查并確定 XML 文件的內(nèi)容與建模數(shù)據(jù)對(duì)應(yīng)的結(jié)構(gòu)相匹配。
例如,給出一個(gè)針對(duì)聯(lián)系(contact)數(shù)據(jù)庫(kù)的簡(jiǎn)單 XML 結(jié)構(gòu),您希望定義一種結(jié)構(gòu)來(lái)指定聯(lián)系人的姓名、地址和電話號(hào)碼。使用 DTD 方法可以使您映射這種結(jié)構(gòu)并確保結(jié)構(gòu)中的每一個(gè)聯(lián)系人與布局相匹配。
例如,清單 2 中顯示了針對(duì)聯(lián)系數(shù)據(jù)庫(kù)的 DTD。
清單 2. 用于聯(lián)系數(shù)據(jù)庫(kù)的 DTD
|
DTD 定義了描述聯(lián)系人所需要的元素、屬性(以及這些屬性所支持的值)。例如,在 清單 2 可以看到,phone 元素有一個(gè) type 屬性,而 address 和其中的 component 元素也有屬性。
使用 DTD 可以幫助確保屬性的有效性,并且,和驗(yàn)證過(guò)程一起使用時(shí)可以識(shí)別任何問(wèn)題。當(dāng)和支持 XML 的編輯器一起使用時(shí),DTD 可以幫助編輯和自動(dòng)完成內(nèi)容。
XSDs,即模式,可以執(zhí)行很多與 DTD 相同的功能,但有其獨(dú)特的用途。例如,一些 XML 編輯器需要使用 DTD 自動(dòng)完成內(nèi)容,然而模式在設(shè)計(jì)文檔實(shí)際層次結(jié)構(gòu)方面更加靈活。您可以根據(jù)具體環(huán)境選擇工具。
![]() ![]() |
![]()
|
查看清單 3,能否找出其中的問(wèn)題?
清單 3. 驗(yàn)證示例
|
手動(dòng)查找問(wèn)題非常麻煩。但是可以通過(guò) xmllint(一款可以檢驗(yàn) XML 文件的內(nèi)容和結(jié)構(gòu)的免費(fèi)工具)運(yùn)行文件,您可以查看運(yùn)行該文件的輸出,如清單 4 所示。
清單 4. 通過(guò) xmllint 運(yùn)行清單 3 得到的輸出
|
盡管與最初的問(wèn)題(其中的一個(gè)屬性沒有結(jié)束)相比似乎復(fù)雜了很多,但卻為您查找問(wèn)題提供了一個(gè)起點(diǎn)。
xmllint 還支持各種各樣的命令行選項(xiàng),幫助選擇診斷方法和結(jié)果。其中最有用的一個(gè)選項(xiàng)是
--noout
,它阻止 xmllint 在解析文件時(shí)回傳內(nèi)容。對(duì)于較短的文件來(lái)說(shuō)沒有什么影響,但對(duì)于大型文件來(lái)說(shuō)則是一個(gè)問(wèn)題。
如果正在使用 DTD,那么使用
--postvalid
選項(xiàng)告訴 xmllint 針對(duì) DTD 驗(yàn)證內(nèi)容,確保內(nèi)容不僅是有效的 XML,而且還與 DTD 的結(jié)構(gòu)相匹配。如果將
使用 DTD 或 XSD
為 contact 文件生成的 DTD 添加到文件,那么屬性定義錯(cuò)誤將被糾正,但隨后將生成一個(gè)不同的錯(cuò)誤,如清單 5 所示。
清單 5. xmllint 找到不同的錯(cuò)誤
|
這樣使用 xmllint 可以方便快捷地確定文檔的結(jié)構(gòu)是否有效。xmllint 是 libxml2 工具箱的一部分,該工具箱已綁定到 Linux、UNIX? 和 Mac OS X,但 Windows? 需要獨(dú)立下載。有關(guān) xmllint 和 libxml2 的更多信息,請(qǐng)參見 參考資料 。
![]() ![]() |
![]()
|
使用 xmllint 和類似工具驗(yàn)證 XML 文件(特別是如果使用了 DTD),是驗(yàn)證 XML 文件內(nèi)容的很好方法。然而,這種方法也有其局限性。例如,如何處理 XML 文件的內(nèi)容?
使用 DTD 或 XSD,您可以為屬性指定明確的內(nèi)容。您只是創(chuàng)建了帶有一個(gè)字符串或 ID 的屬性(可以是受限制的可用選項(xiàng)列表的一部分),但是不能使用這種方式控制或限制元素的內(nèi)容。
例 如,在聯(lián)系人示例中,telephone numbers 元素包含數(shù)字和空格。但是沒辦法阻止用戶向該元素添加字母字符。這樣做在使用 xmllint 進(jìn)行驗(yàn)證時(shí)不會(huì)檢查出錯(cuò)誤,并且編輯器和其他支持 XML 的解決方案也無(wú)法解決或識(shí)別這個(gè)問(wèn)題。應(yīng)用程序出現(xiàn)的故障可能和您預(yù)料的一樣,因?yàn)樗R(shí)別出一個(gè)非標(biāo)準(zhǔn)數(shù)據(jù)類型。
簡(jiǎn)而言之,XML 驗(yàn)證只能保證結(jié)構(gòu)正確,而無(wú)法保證數(shù)據(jù)的有效性。
解決此問(wèn)題的最簡(jiǎn)單方法是編寫一個(gè)解析器,它可以讀取 XML 文件并實(shí)際驗(yàn)證數(shù)據(jù)內(nèi)容。但是不要過(guò)度地驗(yàn)證內(nèi)容,只需確保數(shù)據(jù)符合應(yīng)用程序的要求。
![]() ![]() |
![]()
|
對(duì)于究竟是使用屬性還是元素來(lái)描述希望在 XML 文件中呈現(xiàn)的信息,人們存在著不同的看法。
一般的做法是,使用元素(即標(biāo)記之間的數(shù)據(jù))定義文件包含的信息,而屬性則用于提供所描述數(shù)據(jù)的擴(kuò)展限制。
元素和屬性都各有弊端。例如,屬性不能夠在標(biāo)記中重復(fù),這是元素優(yōu)于屬性的典型例子。元素支持重復(fù)信息的能力使其非常實(shí)用。相反,使用元素限制數(shù)據(jù)有時(shí)處理起來(lái)會(huì)比較復(fù)雜。
聯(lián)系人示例中的電話號(hào)碼很好地解釋了屬性的優(yōu)點(diǎn)。在這個(gè)示例中,如清單 6 所示,使用屬性限制電話號(hào)碼的類型(例如辦公、住宅或移動(dòng)電話)。
清單 6. 限制電話號(hào)碼的類型
|
使用這種結(jié)構(gòu),能夠輕松地把號(hào)碼作為一個(gè)整體(忽略屬性),或者挑選特定的電話號(hào)碼類型(使用屬性)。
將此結(jié)構(gòu)與清單 7 中只使用元素設(shè)計(jì)的結(jié)構(gòu)進(jìn)行比較。
清單 7. 只使用元素限制電話號(hào)碼
|
現(xiàn)在還很難判斷孰優(yōu)孰劣。盡管從理論上說(shuō)任何 XML 解析器或適當(dāng)?shù)?XPath 定義都可以把您需要的信息抽取出來(lái)。但這樣做獲益不大,并且使得 XML 文檔很難閱讀。
![]() ![]() |
![]()
|
在處理 XML 數(shù)據(jù)時(shí),查找需要的信息非常復(fù)雜。您可以編寫一個(gè)解析器來(lái)挑選需要的信息,但在某些情況下,您只需要快速地找到文件中的一小段信息。
例如,如果需要從聯(lián)系人 XML 文件中提出所有國(guó)家的列表,以便查看聯(lián)系人在全球的分布范圍,那么可以使用 XPath 來(lái)挑選信息。
通過(guò)將 XML 文件的結(jié)構(gòu)作為查詢的一部分,XPath 使您能夠從 XML 文件中抽取數(shù)據(jù)。例如,通過(guò)提供特定元素在 XML 文件中的路徑,您可以提取該元素的數(shù)據(jù):
$ xpath contacts.xml '//contact/address/country' |
您可以按照下面這樣分析內(nèi)容:
- 最開頭的雙斜杠(//)表示在文檔的任意位置查找指定的元素(contact)。
- 下一個(gè)斜杠和元素名指定了要查找的下一個(gè)元素(address)— 就是說(shuō),在 contact 元素內(nèi)查找 address 元素。
- 最后的斜杠重復(fù)此過(guò)程,這一次查找的是 country 元素。
注意,在這個(gè)示例中,您限定了從中選擇信息的地址的類型,因此將選擇所有地址。您可以在清單 8 中查看 XPath 查詢的結(jié)果。
清單 8. XPath 查詢的結(jié)果
|
如果需要挑選更具體的數(shù)據(jù),可以指定要匹配的元素或?qū)傩缘膬?nèi)容。例如,如果只選擇手機(jī)號(hào)碼,您需要指定屬性類型和值。為此,使用(@)符號(hào),它表示您要求搜索一個(gè)屬性,然后指定需要匹配的值(參加清單 9 )。
清單 9. 只選擇手機(jī)號(hào)碼
|
清單 8 和 9 都使用了一個(gè)命令行工具。很多 XML 工具箱都提供了原生方法來(lái)處理 XPath 元素,并且您可以使用 XPath 規(guī)范提取數(shù)據(jù)在應(yīng)用程序中直接使用,而不需要使用解析器來(lái)獲取信息。
![]() ![]() |
![]()
|
盡管有些意想不到,但您并一定需要使用一種功能完善的 XML 解析器,使用 SAX、DOM 或其他技術(shù)(如 XPath 或 XQuery)從 XML 文件中提取需要的信息。
XML 文件使用結(jié)構(gòu)化的格式包含數(shù)據(jù),但是有時(shí)您需要信息使用自身的結(jié)構(gòu)化格式。要快速查找一個(gè)信息片段時(shí),通常可以使用更簡(jiǎn)單的解決方法。
通常,您僅需使用 grep、Perl 或其他類似工具提取所需的數(shù)據(jù),而不需要以 XML 文件的形式實(shí)際解釋文檔的結(jié)構(gòu)或內(nèi)容。
例如,您可以使用 grep 選擇電話號(hào)碼(參見清單 10)。
清單 10. 使用 grep 選擇電話號(hào)碼
|
您使用 grep 選擇了需要的信息,并且不需要考慮信息是 XML 格式或者信息的結(jié)構(gòu)。
如果需要查找簡(jiǎn)短的信息片段,簡(jiǎn)化的處理技術(shù)可以查找到所需的信息,并且避免了使用傳統(tǒng)解析方法的開銷。
![]() ![]() |
![]()
|
當(dāng)為文檔構(gòu)建一個(gè)解析器以獲得所需信息時(shí),常常很難決定何時(shí)使用基于 SAX 的處理程序,何時(shí)使用基于 DOM 的處理程序。
關(guān)于這個(gè)問(wèn)題的最簡(jiǎn)單解決方法是同時(shí)考慮文檔的復(fù)雜性和所查找信息的用途。如果要轉(zhuǎn)換文檔,或者文檔非常大,那么 SAX 是最佳選擇。
SAX 逐個(gè)解析文檔元素,在識(shí)別元素時(shí)調(diào)用方法或函數(shù)。如果將一個(gè) XML 文檔轉(zhuǎn)換為另一種格式,例如將 XML 轉(zhuǎn)換成 HTML,那么 SAX 是最有效的方式。您不必將整個(gè)文檔加入到內(nèi)存中,只需響應(yīng)被識(shí)別出的元素和結(jié)構(gòu)。
SAX 的缺點(diǎn)是,如果需要保存或記錄結(jié)構(gòu),或者理解整個(gè)文檔并從其中挑選單個(gè)元素(例如,從所有記錄中選擇單個(gè)聯(lián)系人),則必須構(gòu)建復(fù)雜的處理程序,以加載數(shù)據(jù)并將數(shù)據(jù)記錄到結(jié)構(gòu)中,然后將元素標(biāo)識(shí)到輸出目標(biāo)中。
![]() ![]() |
![]()
|
DOM 可以將整個(gè)文檔及其結(jié)構(gòu)載入到內(nèi)存,并允許您在應(yīng)用程序內(nèi)部引用和使用 XML 文檔的結(jié)構(gòu)。如在聯(lián)系人示例中,您可以將整個(gè)聯(lián)系人數(shù)據(jù)庫(kù)讀入內(nèi)存,然后通過(guò)遍歷聯(lián)系人選擇所有的電話號(hào)碼,接著在每個(gè)聯(lián)系人內(nèi)部遍歷每個(gè)電話號(hào)碼。
由于 DOM 保留了結(jié)構(gòu),更重要的是可以理解和處理結(jié)構(gòu),您可以輕松地對(duì)結(jié)構(gòu)進(jìn)行整體或單獨(dú)的處理。仍然以聯(lián)系人示例為例,使用 SAX 插入新的聯(lián)系人將非常復(fù)雜。但是如果使用 DOM,您只需將一個(gè)表示新聯(lián)系人的新 XML 元素插入到現(xiàn)有的 XML 文檔。
DOM 的缺陷是使用流方式處理文件 — 例如,轉(zhuǎn)換為 HTML — 過(guò)于復(fù)雜,因?yàn)楸仨氃诮Y(jié)構(gòu)內(nèi)逐個(gè)遍歷每個(gè)元素來(lái)處理文檔。
此 外,由于 DOM 在解析其間將整個(gè) XML 文檔載入到內(nèi)存中,DOM 解析器會(huì)變得非常慢并且需要更多的內(nèi)存。但 DOM 處理這樣做也有一些好處;例如,在一次解析過(guò)程中,可以對(duì)使用 DOM 解析的 XML 文檔進(jìn)行多次處理。而使用 SAX,則需要多次重復(fù)解析過(guò)程才能獲得相同的效果。
訪問(wèn) 參考資料 ,查找更多關(guān)于使用 DOM 和 SAX 的信息。
![]() ![]() |
![]()
|
如果經(jīng)常需要編寫和使用 XML,那么必須擁有一個(gè)良好的 XML 編輯器。XML 編輯器不同于標(biāo)準(zhǔn)的文本編輯器,前者可以理解 XML 的結(jié)構(gòu)和布局。XML 編輯器提供的豐富特性使處理 XML 更加簡(jiǎn)單,這些特性包括:
- 完成 — 為一個(gè)快完成的元素輸入字符,編輯器可以自動(dòng)幫您輸入剩下的內(nèi)容。
- 內(nèi) 容完成 — 如果對(duì) XML 文件使用 DTD,那么編輯器可以為您填充并格式化部分內(nèi)容。例如,在 contacts DTD 中,phone 元素的 type 屬性是一個(gè)必需元素。使用智能 XML 編輯器,在創(chuàng)建 phone 標(biāo)記時(shí),該屬性(值為空)將自動(dòng)引入到文本中。
- 內(nèi)聯(lián)格式化 — 編輯器可以使您的 XML 更加易于閱讀和理解。這可以在編輯時(shí)立即實(shí)現(xiàn),也可以通過(guò)單獨(dú)的格式命令實(shí)現(xiàn)。最終得到可以理解并可以更快速地標(biāo)識(shí)的 XML。
- 內(nèi)置驗(yàn)證 — 在輸入內(nèi)容時(shí),編輯器可以驗(yàn)證 XML 文檔的錯(cuò)誤,在編輯器中立即突出顯示各種問(wèn)題,這樣您就知道該如何解決這些問(wèn)題。
- 內(nèi)置翻譯和轉(zhuǎn)換 — 一些 XML 編輯器包括 XPath、XQuery 界面,某些情況下還包括 XSLT 和其他轉(zhuǎn)換的界面,因此可以在編輯環(huán)境中查看轉(zhuǎn)換結(jié)果。
- 學(xué)習(xí)和操作 — 有時(shí)您在 DTD 之前創(chuàng)建 XML 結(jié)構(gòu)。在這種情況下,編輯器可以讀取 XML 文件,學(xué)習(xí)它的結(jié)構(gòu)并創(chuàng)建一個(gè) DTD 進(jìn)行驗(yàn)證,這樣可以為您節(jié)省大量的時(shí)間和精力。
好的 XML 編輯器包括 Eclipse 和 oXygenXML,但是還有很多其他選擇。
![]() ![]() |
![]()
|
養(yǎng)成良好的 XML 處理習(xí)慣,一切將大有不同,包括利用 XML 提供的功能、打破 XML 標(biāo)準(zhǔn)進(jìn)行驗(yàn)證的基礎(chǔ)知識(shí)以及正確處理解析。本文可以幫助您學(xué)習(xí)這 10 個(gè)好習(xí)慣,從而提高處理 XML 文檔和數(shù)據(jù)的效率。
以上轉(zhuǎn)自:http://www.ibm.com/developerworks/cn/xml/x-tengoodxmlhabits/?S_TACT=105AGX52&S_CMP=tec-csdn
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
