1. 認識 XML
雖然今天 JSON 已成為標準,但在 Java 生態中仍有大量的舊有程式碼,因此你有時仍會遇到 XML。了解它是有幫助的。 XML(eXtensible Markup Language) 是用來儲存與交換結構化資料的文字格式。它常被用於設定檔、系統間交換、資料儲存,甚至物件序列化。
XML 文件結構的基本要素:
標籤(元素):
位於 < 和 > 之間的一切。每個標籤都有開頭(<tag>)與結尾(</tag>),或採用自我結束寫法(<tag/>)。
屬性:
元素標籤中的額外參數。
範例: <user name="Vasya" age="25"/>
文字節點:
標籤之間的文字。
範例: <greeting>你好,世界!</greeting>
簡單的 XML 文件範例
<?xml version="1.0" encoding="UTF-8"?>
<users>
<user name="Vasya" age="25">你好!</user>
<user name="Katya" age="30"/>
</users>
說明:
- <users> — 根元素。
- <user> — 具有屬性 name 和 age 的元素;第一個使用者還有文字內容。
2. 關鍵概念
Prolog(XML 宣告):
檔案開頭的一行,用來指定 XML 版本與編碼。
範例: <?xml version="1.0" encoding="UTF-8"?>
元素:
XML 的基本構成單位。
範例: <book>...</book>
屬性:
出現在開始標籤中的參數。
範例: <book title="Java" author="Ivanov"/>
註解:
與 HTML 類似,寫在 <!-- ... --> 之間。
範例: <!-- 這是一則註解 -->
CDATA 區段:
允許插入不會被當成 XML 解析的文字(例如包含 <、& 等符號)。
範例:
<script><![CDATA[
if (a < b && b > 0) { ... }
]]></script>
3. 為什麼 XML 需要命名空間(namespaces)
問題:名稱衝突
在大型 XML 文件中,常會出現名稱相同但語意不同的標籤。例如,你可能同時有作為 HTML 一部分的 <table>,以及屬於商業邏輯(例如資料庫)的一個 <table>。該如何分辨每個標籤的含義?
沒有命名空間:
<root>
<table>
<row>...</row>
</table>
<table>
<column>...</column>
</table>
</root>
在這裡無法判斷每個 <table> 的所屬與意義。
解法:命名空間
Namespace(命名空間)是一種用來「標記」元素與屬性的方式,以避免名稱衝突並清楚區分不同標籤的語意。
- 每個命名空間是一個唯一的 URI(看起來像網址,但只是識別子)。
- 屬於不同命名空間的元素與屬性被視為不同,即使名稱相同。
優點:
- 不同標準與綱要之間不會發生命名衝突。
- 可以在同一文件中合併來自不同來源的資料。
- 可以清楚看出每個標籤屬於哪個「詞彙」。
4. 使用命名空間:宣告與套用
如何宣告命名空間
在元素的開始標籤上寫入特殊屬性 xmlns(XML Namespace):
- 無前綴: xmlns="URI" — 為所有內部元素宣告預設命名空間。
- 具前綴: xmlns:prefix="URI" — 宣告一個帶有短名稱(前綴)的命名空間,供標籤使用。
宣告與使用命名空間的範例
<root xmlns:h="http://www.w3.org/TR/html4/"
xmlns:f="http://www.w3schools.com/furniture">
<h:table>
<h:tr>
<h:td>儲存格 1</h:td>
<h:td>儲存格 2</h:td>
</h:tr>
</h:table>
<f:table>
<f:name>桌子</f:name>
<f:width>80</f:width>
<f:length>120</f:length>
</f:table>
</root>
說明:
- xmlns:h="..." — 為 HTML 表格宣告前綴 h。
- xmlns:f="..." — 為家具宣告前綴 f。
- <h:table> 與 <f:table> — 現在為不同元素,即使名稱相同。
如何使用命名空間
- 宣告: 在根元素或任何其他元素上:xmlns:prefix="URI"
- 使用: 在元素或屬性的名稱前加上前綴與冒號:<prefix:element>...</prefix:element>
預設命名空間
若只宣告 xmlns="URI",所有沒有前綴的元素都會屬於此命名空間。
<books xmlns="http://example.com/books">
<book>...</book>
</books>
5. 實作:建立一個含多個命名空間的簡單 XML 文件
我們來建立一個範例 XML 文件,使用兩個命名空間:一個給 HTML,一個給家具。
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:h="http://www.w3.org/TR/html4/"
xmlns:f="http://www.w3schools.com/furniture">
<h:table>
<h:tr>
<h:td>儲存格 1</h:td>
<h:td>儲存格 2</h:td>
</h:tr>
</h:table>
<f:table>
<f:name>桌子</f:name>
<f:width>80</f:width>
<f:length>120</f:length>
</f:table>
</root>
這裡發生了什麼:
- 在根元素上宣告了兩個命名空間:h 與 f。
- 所有帶有前綴 h: 的元素屬於 HTML 表格。
- 所有帶有前綴 f: 的元素屬於家具。
6. 常見錯誤
錯誤 1:忘記宣告前綴
<root>
<h:table>...</h:table>
</root>
結果: XML 解析器會報錯: The prefix 'h' for element 'h:table' is not bound.
錯誤 2:沒有命名空間且名稱相同
<root>
<table>...</table>
<table>...</table>
</root>
結果: 無法區分每個 <table> 分別代表什麼.
錯誤 3:前綴使用不正確
<root xmlns:h="http://www.w3.org/TR/html4/">
<h:table>...</h:table>
<f:table>...</f:table> <!-- 錯誤:未宣告前綴 f -->
</root>
結果: 解析器錯誤: The prefix 'f' for element 'f:table' is not bound.
GO TO FULL VERSION