跳到主要內容

← 返回部落格

XML 是什麼?結構、well-formed vs valid,以及 XML 與 JSON 的取捨

XML(可延伸標記語言)比 JSON 更早出現,雖然 JSON 贏了 API 世界,但 XML 遠遠沒有消失:SVG、RSS/Atom、Office 文件(.docx)、Android 版面、Maven pom.xml、SOAP 全都是 XML。會讀、會整理它,至今仍是實用技能。

格式化工具不該動到語意。 我們把 <feed><item id="1"><title>Hello</title></item><item id="2"><title/></item></feed> 丟進 XML 格式化工具:

<feed>
  <item id="1">
    <title>Hello</title>
  </item>
  <item id="2">
    <title/>
  </item>
</feed>

自閉合的 <title/> 仍然是自閉合,沒有被展開成 <title></title>,id 屬性也完全沒動。這個區別是有意義的:在 XML 規範裡那兩種寫法等價,但下游用字串比對的程式可能不同意 —— 所以一個「順手幫你整理」的格式化工具,其實改了你的資料。這裡唯一變的只有縮排。

XML 的結構

XML 用巢狀的元素(以標籤包起來)描述資料,元素可帶屬性:

<book id="42" lang="zh">
  <title>哈比人</title>
  <author>托爾金</author>
</book>

每個開標籤都要有對應的閉標籤(或自閉,<br/>),標籤必須正確巢狀,屬性值要加引號。任何一項出錯,文件就無法解析。

結構在「被放回去」的時候最容易看清楚。下面是一行 XML,兩個 item,其中一個標題是空的:

<feed><item id="1"><title>Hello</title></item><item id="2"><title/></item></feed>

而這是我們自己的 XML 格式化工具回傳的結果:

<feed>
  <item id="1">
    <title>Hello</title>
  </item>
  <item id="2">
    <title/>
  </item>
</feed>

沒有東西被加上或拿掉 —— 只有空白。注意 <title/> 保持自我關閉,沒有被展開成 <title></title>:這兩者在 XML 裡等價,而一個「好心」把其中一個改寫成另一個的格式化工具,改動的是某些簽章或 diff 賴以為生的位元組。

well-formed vs valid —— 一個重要區別

這兩個聽起來很像,其實不同:

  • **格式正確(well-formed)**指 XML 遵守上述語法規則——標籤、巢狀、引號都對。任何 XML 解析器都能檢查。
  • 有效(valid)指它還符合某個綱要(schema)(DTD 或 XSD),那定義了允許哪些元素與屬性,需要有綱要才能驗。

大多數線上工具——包含我們的——檢查的是 XML「格式正確」。這能抓到日常錯誤(沒閉合的標籤、多出來的 &),而那些正是實務上讓解析失敗的原因。

XML vs JSON:何時用哪個

  • JSON 更輕量,是網頁 API 與程式讀取設定檔的預設。
  • XML 在需要屬性、混合內容(文字與元素並存)、命名空間、註解,或某個生態系已標準化用它(SVG、RSS、Office 格式)時更合適。

與其說是競爭對手,不如說是解決不同問題的工具。

XML、JSON、HTML 並排比較

面向XMLJSONHTML
用途儲存/傳輸資料儲存/傳輸資料呈現文件
標籤自訂,可任意命名無標籤(用大括號)固定一組(<p>、<div>)
屬性有無(只有鍵)有
嚴格程度必須格式正確嚴格寬鬆,瀏覽器會容錯
註解<!-- -->無<!-- -->

XML 與 HTML 長得像,因為兩者都源自 SGML;但 XML 讓你自創標籤且語法嚴格,HTML 則是固定字彙、瀏覽器容忍馬虎的標記。XHTML 就是想讓 HTML 遵守 XML 規則的嘗試。

實際例子:RSS

RSS 訂閱其實就是用約定好標籤名的 XML:

<rss version="2.0">
  <channel>
    <title>我的部落格</title>
    <item>
      <title>第一篇</title>
      <link>https://example.com/first</link>
    </item>
  </channel>
</rss>

SVG 圖檔也一樣——<svg> 文件就是 XML,你可以用文字編輯器打開、手動編輯。

常見陷阱

  • 特殊字元要跳脫。 文字中有五個字元需要用實體表示:&lt;(<)、&gt;(>)、&amp;(&)、&quot;(")、&apos;(')。一個沒跳脫的 & 是訂閱源壞掉最常見的原因。
  • XML 區分大小寫。 <Title> 和 <title> 是不同元素,閉標籤必須完全一致。
  • 只能有一個根元素。 格式正確的文件,最外層只能有唯一一個元素包住其餘全部。

因為 SVG 就是 XML,你手動編輯向量圖時也適用同一套整理方式——看我們的 PNG 轉 SVG 介紹。

那個縮排也正是一個常見誤解住的地方。就 XML 的資料模型而言,元素之間的空白仍然是文字,所以解析器可能在你以為「只有子元素」的地方回報一個文字節點。把 <feed><item id="1"><title>Hello</title></item><item id="2"><title/></item></feed> 重新排版成上面的縮排版本不會改變文件的意義,但會改變 firstChild 回傳什麼 —— 這就是為什麼 XML 的函式庫有專門的「可忽略空白」設定,而 JSON 沒有對應的問題。

在瀏覽器本機格式化與驗證

XML 格式化工具把雜亂的 XML 美化成好讀的縮排結構、壓回一行,並指出語法錯誤——全程在本機,再敏感的設定檔也不離開你的裝置。

相關工具