Namespace 問題
在上一篇文章『HTML 資訊汲取(中篇) - Default namespace 問題』中提到:在 XPath 中,沒有所謂 default namespace (預設命名空間)。若 XPath 路徑未使用 prefix (前置字符) 指明 namespace,則其對應的 namespace 為 empty namespace (空命名空間)。因此,若在 XML 文件中定義了 default namespace,則所有的標籤必定都歸屬於某個不為空的 namespace。此時,未指明 namespace 的 XPath 路徑,將對應不到任何元素。
另一方面,TagSoup 處理過的 HTML 文件,有三個與 namespace 有關的問題:
- TagSoup 處理過的 HTML 文件,一律輸出為 XHTML 格式,並且定義了
xmlns="http://www.w3.org/1999/xhtml"
這個 default namespace,以及xmlns:html="http://www.w3.org/1999/xhtml"
這個以html
為 prefix 的 namespace。而其餘的 namespace 的定義,都將被移除。 - 由於 TagSoup 處理過的 HTML 文件,含有 default namespace 的定義,使用 XPath 選取元素時,一定要在路徑的標籤或屬性前,加上
html
這個 prefix,才能對應到元素。 - TagSoup 處理過的 HTML 文件,其元素標籤若含有 prefix 定義,即使 prefix 是
html
,都會被修改並對應到urn:x-prefix:html
這樣的 URI(參考 TagSoup 原始碼中 Parser 類別的 foreign() 函數、ElementType 類別的 namespace() 函數以及 change log),因而使該標籤對應不到原本正確的 namespace 的 URI。導致使用了該 prefix 的 XPath 路徑,也對應不到正確的標籤。(原本應該能正確對應的,這一點可以經由使用 JDOM 內建的 XML 解析器的實驗證明。)
思考可能的解決方案
內建的 XML 解析器不會有 namespace 的問題,但是無法處理 non-well-formed HTML。顯然此路不通…。
TagSoup 可以處理 non-well-formed HTML,但是會有 namseapce 問題。該是時候放棄 TagSoup,另找一個 HTML 解析器了嗎?還是如果我們可以配合 TagSoup 輸出的 namespace 定義,在 XPath 中一律使用 html
prefix;或是,相反地,讓 TagSoup 不輸出 namespace 。是否就可以解決問題呢?(雖然邏輯上還存在著一個完美的可能性,就是讓 TagSoup 不輸出 default namespace,也同時能保留外部 namespace 的定義,不過這並不容易達到。這已牽涉到 TagSoup 的設計架構了,除非大幅修改 TagSoup 的架構,讓它正確處理外部 namespace 的定義。但是這已經超出本文的目的了。)