使用XML的10種好習慣

人們都很喜歡 XML 以及它所提供的靈活性和互操作性,但是,通過使用一些技巧,可以使與 XML 的互操作和與 XML 一起使用的工具更加簡單。在處理 XML 時養成一些良好的習慣可以保證最高效地利用您的 XML 文檔和應用程序。

 




回頁首


使用 10 種良好的習慣

以下是 10 種最良好的 XML 習慣:

  1. 定義 XML 和編碼
  2. 使用 DTD 或 XSD
  3. 記得進行驗證
  4. 驗證並不總是能夠解決問題
  5. XML 結構和屬性
  6. 使用 XPath 查找信息
  7. 並不總是需要使用解析器提取信息
  8. 何時使用 SAX 而非 DOM 解析
  9. 何時使用 DOM 而非 SAX 解析
  10. 使用良好的 XML 編輯器

 




回頁首


定義 XML 和編碼

經常使用的縮寫詞
  • DOM:文檔對象模型(Document Object Model)
  • DTD:文檔類型定義(Document Type Definition)
  • HTML:超文本標記語言(Hypertext Markup Language)
  • IDE:集成開發環境(Integrated Development Environment)
  • SAX:XML 簡單 API(Simple API for XML)
  • XSD:XML 模式定義(XML Schema Definition)
  • XML:可擴展標記語言(Extensible Markup Language)
  • XSLT:可擴展樣式表語言轉換(Extensible Stylesheet Language Transformations)

在快速創建 XML 文檔時,一般都會傾向於創建基本的結構並避開一些普通 XML 文檔需求,包括指定 XML 文檔聲明和 XML 文檔包含的數據的編碼類型。

考慮清單 1 所示的 XML 文檔。


清單 1. 未包含 XML 聲明和數據編碼類型的 XML 文檔

                
<phrases>
<phrase lang="en">Hello</phrase>
<phrase lang="it">Buongiorno</phrase>
<phrase lang="fr">Salut!</phrase>
</phrases>

 

對於普通人來說,可以查看該文檔並將其識別爲 XML,但是對於計算機來說,則很難作出這樣的判斷。在文件頂部添加 XML 聲明,可以使它更加明確、更容易識別。一行簡單的代碼就可以說明文檔是 XML,並且指出版本號和 XML 數據使用的字符編碼類型。例如:

<?xml version="1.0" encoding="us-ascii"?>

 

編碼說明中的內容也應該確保正確性。XML 解析器使用編碼確保 XML 文檔的單個字符被正確載入。例如,繼續 清單 1 中基於短語的示例,如果向文檔添加一個俄語條目,則會出現問題,因爲目前指定的編碼不支持擴展的字符集(使用俄語短語表示 hello 時要求使用擴展字符集)。

指定錯誤的編碼意味着解析器不能正確處理文檔;例如,如果將一個多字節擴展字符讀取爲一個單字節組成的序列,那麼會導致數據的損壞和不良輸出。

 




回頁首


使用 DTD 或 XSD

添加了 XML 聲明後,應該確保使用 DTD 或 XSD 定義有效的 XML 文件的結構。這兩種方法都允許 XML 解析器檢查並確定 XML 文件的內容與建模數據對應的結構相匹配。

例如,給出一個針對聯繫(contact)數據庫的簡單 XML 結構,您希望定義一種結構來指定聯繫人的姓名、地址和電話號碼。使用 DTD 方法可以使您映射這種結構並確保結構中的每一個聯繫人與佈局相匹配。

例如,清單 2 中顯示了針對聯繫數據庫的 DTD。


清單 2. 用於聯繫數據庫的 DTD

                
<!ELEMENT phone (#PCDATA)>
<!ATTLIST phone type (home | work | mobile) #REQUIRED>
<!ELEMENT contact (#PCDATA | name | phone | address)*>
<!ELEMENT contacts (#PCDATA | contact)*>
<!ELEMENT country (#PCDATA)>
<!ELEMENT road (#PCDATA)>
<!ELEMENT address (#PCDATA | road | city | state | postcode | country)*>
<!ATTLIST address type (home | work) #REQUIRED>
<!ELEMENT state (#PCDATA)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT postcode (#PCDATA)>
<!ELEMENT city (#PCDATA)>

 

DTD 定義了描述聯繫人所需要的元素、屬性(以及這些屬性所支持的值)。例如,在 清單 2 可以看到,phone 元素有一個 type 屬性,而 address 和其中的 component 元素也有屬性。

使用 DTD 可以幫助確保屬性的有效性,並且,和驗證過程一起使用時可以識別任何問題。當和支持 XML 的編輯器一起使用時,DTD 可以幫助編輯和自動完成內容。

XSDs,即模式,可以執行很多與 DTD 相同的功能,但有其獨特的用途。例如,一些 XML 編輯器需要使用 DTD 自動完成內容,然而模式在設計文檔實際層次結構方面更加靈活。您可以根據具體環境選擇工具。

 




回頁首


記得進行驗證

查看清單 3,能否找出其中的問題?


清單 3. 驗證示例

                
<contacts>
<contact>
<name>Martin</name>
<phone type="home">123 456 7890</phone>
<phone type="mobile">123 456 7890</phone>
<phone type="work">123 456 7890</phone>
<address type="home">
<road>Home road</road>
<city>Home city</city>
<state>Home state</state>
<zipcode>12434</zipcode>
<country>USA</country>
</address>
</contact>
<contact>
<name>Sharon</name>
<phone type="work">234 567 8901</phone>
<phone>234 567 8901</phone>
<address type="home">
<road>Other home road</road>
<city>Other city</city>
<state>Other state</state>
<zipcode>39487</zipcode>
<country>USA</country>
</address>
<address type="work>
<road>Work building, work road</road>
<city>Work city</city>
<state>Work state</state>
<zipcode>12347</zipcode>
<country>USA</country>
</address>
</contact>
</contacts>

 

手動查找問題非常麻煩。但是可以通過 xmllint(一款可以檢驗 XML 文件的內容和結構的免費工具)運行文件,您可以查看運行該文件的輸出,如清單 4 所示。


清單 4. 通過 xmllint 運行清單 3 得到的輸出

                
$ xmllint contacts.xml
contacts.xml:27: parser error : Unescaped '<' not allowed in attributes values
<road>Work building, work road</road>
^
contacts.xml:27: parser error : attributes construct error
<road>Work building, work road</road>
^
contacts.xml:27: parser error : Couldn't find end of Start Tag address line 26
<road>Work building, work road</road>
^
contacts.xml:32: parser error : Opening and ending tag mismatch: contact line 15
and address
</address>
^
contacts.xml:33: parser error : Opening and ending tag mismatch: contacts line 1
and contact
</contact>
^
contacts.xml:34: parser error : Extra content at the end of the document
</contacts>

 

儘管與最初的問題(其中的一個屬性沒有結束)相比似乎複雜了很多,但卻爲您查找問題提供了一個起點。

xmllint 還支持各種各樣的命令行選項,幫助選擇診斷方法和結果。其中最有用的一個選項是 --noout,它阻止 xmllint 在解析文件時回傳內容。對於較短的文件來說沒有什麼影響,但對於大型文件來說則是一個問題。

如果正在使用 DTD,那麼使用 --postvalid 選項告訴 xmllint 針對 DTD 驗證內容,確保內容不僅是有效的 XML,而且還與 DTD 的結構相匹配。如果將 使用 DTD 或 XSD 爲 contact 文件生成的 DTD 添加到文件,那麼屬性定義錯誤將被糾正,但隨後將生成一個不同的錯誤,如清單 5 所示。


清單 5. xmllint 找到不同的錯誤

                
$ xmllint --noout --postvalid contacts.xml
contacts.xml:9: element address: validity error : Element zipcode is not declared
in address list of possible children
contacts.xml:21: element address: validity error : Element zipcode is not declared
in address list of possible children
contacts.xml:28: element address: validity error : Element zipcode is not declared
in address list of possible children
Document contacts.xml does not validate

 

這樣使用 xmllint 可以方便快捷地確定文檔的結構是否有效。xmllint 是 libxml2 工具箱的一部分,該工具箱已綁定到 Linux、UNIX® 和 Mac OS X,但 Windows® 需要獨立下載。有關 xmllint 和 libxml2 的更多信息,請參見 參考資料

 




回頁首


驗證並不總是能夠解決問題

使用 xmllint 和類似工具驗證 XML 文件(特別是如果使用了 DTD),是驗證 XML 文件內容的很好方法。然而,這種方法也有其侷限性。例如,如何處理 XML 文件的內容?

使用 DTD 或 XSD,您可以爲屬性指定明確的內容。您只是創建了帶有一個字符串或 ID 的屬性(可以是受限制的可用選項列表的一部分),但是不能使用這種方式控制或限制元素的內容。

例 如,在聯繫人示例中,telephone numbers 元素包含數字和空格。但是沒辦法阻止用戶向該元素添加字母字符。這樣做在使用 xmllint 進行驗證時不會檢查出錯誤,並且編輯器和其他支持 XML 的解決方案也無法解決或識別這個問題。應用程序出現的故障可能和您預料的一樣,因爲它識別出一個非標準數據類型。

簡而言之,XML 驗證只能保證結構正確,而無法保證數據的有效性。

解決此問題的最簡單方法是編寫一個解析器,它可以讀取 XML 文件並實際驗證數據內容。但是不要過度地驗證內容,只需確保數據符合應用程序的要求。

 




回頁首


XML 結構和屬性

對於究竟是使用屬性還是元素來描述希望在 XML 文件中呈現的信息,人們存在着不同的看法。

一般的做法是,使用元素(即標記之間的數據)定義文件包含的信息,而屬性則用於提供所描述數據的擴展限制。

元素和屬性都各有弊端。例如,屬性不能夠在標記中重複,這是元素優於屬性的典型例子。元素支持重複信息的能力使其非常實用。相反,使用元素限制數據有時處理起來會比較複雜。

聯繫人示例中的電話號碼很好地解釋了屬性的優點。在這個示例中,如清單 6 所示,使用屬性限制電話號碼的類型(例如辦公、住宅或移動電話)。


清單 6. 限制電話號碼的類型

                
<phone type="home">123 456 7890</phone>
<phone type="mobile">123 456 7890</phone>
<phone type="work">123 456 7890</phone>

 

使用這種結構,能夠輕鬆地把號碼作爲一個整體(忽略屬性),或者挑選特定的電話號碼類型(使用屬性)。

將此結構與清單 7 中只使用元素設計的結構進行比較。


清單 7. 只使用元素限制電話號碼

                
<phone>
<type>home</type>
<number>123 456 7890</number>
</phone>
<phone>
<type>mobile</type>
<number>123 456 7890</number>
</phone>
<phone>
<type>work</type>
<number>123 456 7890</number>
</phone>

 

現在還很難判斷孰優孰劣。儘管從理論上說任何 XML 解析器或適當的 XPath 定義都可以把您需要的信息抽取出來。但這樣做獲益不大,並且使得 XML 文檔很難閱讀。

 




回頁首


使用 XPath 查找信息

在處理 XML 數據時,查找需要的信息非常複雜。您可以編寫一個解析器來挑選需要的信息,但在某些情況下,您只需要快速地找到文件中的一小段信息。

例如,如果需要從聯繫人 XML 文件中提出所有國家的列表,以便查看聯繫人在全球的分佈範圍,那麼可以使用 XPath 來挑選信息。

通過將 XML 文件的結構作爲查詢的一部分,XPath 使您能夠從 XML 文件中抽取數據。例如,通過提供特定元素在 XML 文件中的路徑,您可以提取該元素的數據:

$ xpath contacts.xml '//contact/address/country'

 

您可以按照下面這樣分析內容:

  • 最開頭的雙斜槓(//)表示在文檔的任意位置查找指定的元素(contact)。
  • 下一個斜槓和元素名指定了要查找的下一個元素(address)— 就是說,在 contact 元素內查找 address 元素。
  • 最後的斜槓重複此過程,這一次查找的是 country 元素。

注意,在這個示例中,您限定了從中選擇信息的地址的類型,因此將選擇所有地址。您可以在清單 8 中查看 XPath 查詢的結果。


清單 8. XPath 查詢的結果

                
$ xpath contacts.xml '//contact/address/country'
Found 3 nodes:
-- NODE --
<country>USA</country>-- NODE --
<country>USA</country>-- NODE --
<country>USA</country>

 

如果需要挑選更具體的數據,可以指定要匹配的元素或屬性的內容。例如,如果只選擇手機號碼,您需要指定屬性類型和值。爲此,使用(@)符號,它表示您要求搜索一個屬性,然後指定需要匹配的值(參加清單 9 )。


清單 9. 只選擇手機號碼

                
$ xpath contacts.xml '//contact/phone[@type="mobile"]'
Found 1 nodes:
-- NODE --
<phone type="mobile">123 456 7890</phone>

 

清單 89 都使用了一個命令行工具。很多 XML 工具箱都提供了原生方法來處理 XPath 元素,並且您可以使用 XPath 規範提取數據在應用程序中直接使用,而不需要使用解析器來獲取信息。

 




回頁首


並不總是需要使用解析器提取信息

儘管有些意想不到,但您並一定需要使用一種功能完善的 XML 解析器,使用 SAX、DOM 或其他技術(如 XPath 或 XQuery)從 XML 文件中提取需要的信息。

XML 文件使用結構化的格式包含數據,但是有時您需要信息使用自身的結構化格式。要快速查找一個信息片段時,通常可以使用更簡單的解決方法。

通常,您僅需使用 grep、Perl 或其他類似工具提取所需的數據,而不需要以 XML 文件的形式實際解釋文檔的結構或內容。

例如,您可以使用 grep 選擇電話號碼(參見清單 10)。


清單 10. 使用 grep 選擇電話號碼

                
$ grep '<phone' contacts.xml

<phone type="home">123 456 7890</phone>
<phone type="mobile">123 456 7890</phone>
<phone type="work">123 456 7890</phone>
<phone type="work">234 567 8901</phone>
<phone>234 567 8901</phone>

 

您使用 grep 選擇了需要的信息,並且不需要考慮信息是 XML 格式或者信息的結構。

如果需要查找簡短的信息片段,簡化的處理技術可以查找到所需的信息,並且避免了使用傳統解析方法的開銷。

 




回頁首


何時使用 SAX 而非 DOM 解析

當爲文檔構建一個解析器以獲得所需信息時,常常很難決定何時使用基於 SAX 的處理程序,何時使用基於 DOM 的處理程序。

關於這個問題的最簡單解決方法是同時考慮文檔的複雜性和所查找信息的用途。如果要轉換文檔,或者文檔非常大,那麼 SAX 是最佳選擇。

SAX 逐個解析文檔元素,在識別元素時調用方法或函數。如果將一個 XML 文檔轉換爲另一種格式,例如將 XML 轉換成 HTML,那麼 SAX 是最有效的方式。您不必將整個文檔加入到內存中,只需響應被識別出的元素和結構。

SAX 的缺點是,如果需要保存或記錄結構,或者理解整個文檔並從其中挑選單個元素(例如,從所有記錄中選擇單個聯繫人),則必須構建複雜的處理程序,以加載數據並將數據記錄到結構中,然後將元素標識到輸出目標中。

 




回頁首


何時使用 DOM 而非 SAX 解析

DOM 可以將整個文檔及其結構載入到內存,並允許您在應用程序內部引用和使用 XML 文檔的結構。如在聯繫人示例中,您可以將整個聯繫人數據庫讀入內存,然後通過遍歷聯繫人選擇所有的電話號碼,接着在每個聯繫人內部遍歷每個電話號碼。

由於 DOM 保留了結構,更重要的是可以理解和處理結構,您可以輕鬆地對結構進行整體或單獨的處理。仍然以聯繫人示例爲例,使用 SAX 插入新的聯繫人將非常複雜。但是如果使用 DOM,您只需將一個表示新聯繫人的新 XML 元素插入到現有的 XML 文檔。

DOM 的缺陷是使用流方式處理文件 — 例如,轉換爲 HTML — 過於複雜,因爲必須在結構內逐個遍歷每個元素來處理文檔。

此 外,由於 DOM 在解析其間將整個 XML 文檔載入到內存中,DOM 解析器會變得非常慢並且需要更多的內存。但 DOM 處理這樣做也有一些好處;例如,在一次解析過程中,可以對使用 DOM 解析的 XML 文檔進行多次處理。而使用 SAX,則需要多次重複解析過程才能獲得相同的效果。

訪問 參考資料,查找更多關於使用 DOM 和 SAX 的信息。

 




回頁首


使用良好的 XML 編輯器

如果經常需要編寫和使用 XML,那麼必須擁有一個良好的 XML 編輯器。XML 編輯器不同於標準的文本編輯器,前者可以理解 XML 的結構和佈局。XML 編輯器提供的豐富特性使處理 XML 更加簡單,這些特性包括:

  • 完成 — 爲一個快完成的元素輸入字符,編輯器可以自動幫您輸入剩下的內容。
  • 內 容完成 — 如果對 XML 文件使用 DTD,那麼編輯器可以爲您填充並格式化部分內容。例如,在 contacts DTD 中,phone 元素的 type 屬性是一個必需元素。使用智能 XML 編輯器,在創建 phone 標記時,該屬性(值爲空)將自動引入到文本中。
  • 內聯格式化 — 編輯器可以使您的 XML 更加易於閱讀和理解。這可以在編輯時立即實現,也可以通過單獨的格式命令實現。最終得到可以理解並可以更快速地標識的 XML。
  • 內置驗證 — 在輸入內容時,編輯器可以驗證 XML 文檔的錯誤,在編輯器中立即突出顯示各種問題,這樣您就知道該如何解決這些問題。
  • 內置翻譯和轉換 — 一些 XML 編輯器包括 XPath、XQuery 界面,某些情況下還包括 XSLT 和其他轉換的界面,因此可以在編輯環境中查看轉換結果。
  • 學習和操作 — 有時您在 DTD 之前創建 XML 結構。在這種情況下,編輯器可以讀取 XML 文件,學習它的結構並創建一個 DTD 進行驗證,這樣可以爲您節省大量的時間和精力。

好的 XML 編輯器包括 Eclipse 和 oXygenXML,但是還有很多其他選擇。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章