XMLCatalog

XMLCatalog 是公共資源的目錄,例如在 XML 文件中引用的 DTD 或實體。目錄通常用於讓 Web 參考資源指向資源的本地快取副本。

這允許 XML 分析器、XSLT 處理器或其他 XML 文件使用者有效地允許本地替換 Web 上提供的資源。

注意:此工作會使用,但不會依賴 Apache Ant 發行版中未包含的外部程式庫。請參閱 程式庫依賴關係 以取得更多資訊。

此資料類型提供基於 OASIS XML 目錄標準 的資源位置目錄。目錄項目用於實體解析和 URI 解析,這符合 Java API for XML 處理 (JAXP) 規格 中定義的 org.xml.sax.EntityResolverjavax.xml.transform.URIResolver 介面。

例如,在 web.xml 檔案中,DTD 參照為

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
  "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">

XML 處理器在沒有 XMLCatalog 支援的情況下,需要從指定的 URL 擷取 DTD,只要需要驗證文件時。

這在建置過程中可能會非常耗時,特別是在網路傳輸量受限的情況下。或者,您可以執行下列操作

  1. web-app_2_2.dtd 複製到您本機磁碟的某個位置(在檔案系統中或甚至嵌入在類別路徑上的 jar 或 zip 檔案中)。
  2. 建立一個 <xmlcatalog>,其中包含一個 <dtd> 元素,其 location 屬性指向該檔案。
  3. 成功!XML 處理器現在將使用本地副本,而不是呼叫網際網路。

XMLCatalog 可以出現在支援此功能的工作中,或與 target 位於同一層級,亦即,作為 project 的子項目,以便在不同工作中重複使用,例如 XML 驗證和 XSLT 轉換。XML 驗證工作使用 XMLCatalog 進行實體解析。XSLT 轉換工作同時使用 XMLCatalog 進行實體和 URI 解析。

XMLCatalog 指定為對另一個 XMLCatalog 的參考(先前在建置檔案中定義),或指定為 dtdentity 位置的清單。此外,外部目錄檔案可以指定在巢狀 catalogpath 中,但除非 xml-commons 的解析器程式庫可在系統類別路徑中使用,否則將會忽略這些檔案。由於在解析器 1.0 發布後解析器程式碼中發生向後不相容的變更,因此 Ant 只支援解析器 1.1 或更新版本。實體解析的個別類別路徑可以透過巢狀 classpath 元素內嵌指定;否則,系統類別路徑也會用於此目的。

XMLCatalog 也可以巢狀在其他 XMLCatalog 內。例如,可以透過包含幾個巢狀 XMLCatalog 來建立一個「超集」XMLCatalog,這些巢狀 XMLCatalog 參照其他先前定義的 XMLCatalog。

資源位置可以內嵌指定,或在外部目錄檔案中指定,或同時使用這兩種方式。為了使用外部目錄檔案,xml-commons 解析器程式庫 (resolver.jar) 必須在您的路徑中。外部目錄檔案可以是 純文字格式XML 格式。如果在類別路徑中找不到 xml-commons 解析器程式庫,則在 catalogpath 中指定的外部目錄檔案將會被忽略,並會記錄警告。然而,在此情況下,內嵌項目的處理將會正常進行。

目前,只有 <dtd><entity> 元素可以內嵌指定;這些元素大致分別對應於 OASIS 目錄項目類型 PUBLICURI。相對地,外部目錄檔案可以使用 OASIS 規格 中定義的任何項目類型。

實體/DTD/URI 解析演算法

當 XML 處理器查詢實體、DTD 或 URI 時,XMLCatalog 會搜尋其條目清單,查看是否有任何相符項。也就是說,它會嘗試比對每個條目的 publicId 屬性,以及要解析實體的 PublicID 或 URI。假設找到相符的條目,XMLCatalog 接著會執行下列步驟

1. 檔案系統查詢

首先會在檔案系統中查詢 location。如果 location 是相對路徑,則會使用 Ant 專案 basedir 屬性作為基本目錄。如果 location 指定絕對路徑,則會原樣使用。一旦我們取得絕對路徑,我們會檢查該路徑是否存在有效且可讀取的檔案。如果存在,我們就完成了。如果不存在,我們會繼續執行下一步。

2. 類別路徑查詢

接著會在類別路徑中查詢 location。請回想一下,jar 檔案只是精美的 zip 檔案。對於類別路徑查詢,location 會原樣使用(不會預先加上基底)。我們會使用 Classloader 嘗試從類別路徑載入資源。例如,如果 hello.jar 在類別路徑中,且其中包含 foo/bar/blat.dtd,它會解析 locationfoo/bar/blat.dtd 的實體。當然,它不會解析 locationblat.dtd 的實體。

3a. Apache xml-commons 解析器查詢

接下來會發生什麼事,取決於 xml-commons 中的解析器函式庫是否在類別路徑中可用。如果是,我們會將所有進一步的解析嘗試都遞延給它。解析器函式庫支援極為精密的函式,例如 URL 重寫等,可以透過在外部目錄檔案中建立適當的條目來存取(XMLCatalog 尚未提供所有在 OASIS 標準 中定義條目的內嵌支援)。

3. URL 空間查詢

最後,我們會嘗試將 location 變成 URL。一開始這看起來似乎會違背 XMLCatalog 的目的,為什麼要再回到網際網路上?但事實上,這可以用於(在某種程度上)實作 HTTP 重新導向,將一個 URL 替換為另一個 URL。對應到的 URL 也可能由本機網路伺服器提供。如果 URL 解析為有效且可讀取的資源,我們就完成了。否則,我們就放棄。在這種情況下,XML 處理器會執行其正常的解析演算法。根據處理器組態,進一步的解析失敗可能會導致致命(即會終止建置)錯誤,也可能不會。

XMLCatalog 屬性

屬性 說明 必要
id XMLCatalog 的唯一名稱,用於從另一個 XMLCatalog 參照 XMLCatalog 的內容
refid 您希望用於此 XMLCatalog 的另一個 XMLCatalog 的 id

XMLCatalog 巢狀元素

dtd/entity

用於指定 XMLCatalog 的 dtdentity 元素在結構上相同

屬性 說明 必要
publicId 定義 dtd 或實體時使用的公開識別碼,例如 "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
location 要針對指定的公開識別碼使用的本地替換位置。這可以指定為檔名、在類別路徑中找到的資源名稱或 URL。相對路徑會根據預設為 Ant 專案 basedir 的基準解析。

classpath

要使用於 實體解析 的類別路徑。巢狀的 <classpath> 是類似 路徑 的結構。

catalogpath

巢狀的 catalogpath 元素是類似 路徑 的結構,列出要搜尋的目錄檔。此路徑中的所有檔都假設為 OASIS 目錄檔,採用 純文字格式XML 格式。指定不存在檔的項目會被忽略。如果 xml-commons 中的解析程式庫在類別路徑中不可用,所有 catalogpath 都會被忽略,並記錄警告。

範例

設定 XMLCatalog,其中包含一個在使用者家目錄中本地參照的 DTD

<xmlcatalog>
    <dtd publicId="-//OASIS//DTD DocBook XML V4.1.2//EN"
         location="/home/dion/downloads/docbook/docbookx.dtd"/>
</xmlcatalog>

設定 XMLCatalog,其中包含多個 DTD,可以在檔案系統(相對於 Ant 專案 basedir)或類別路徑中找到

<xmlcatalog id="commonDTDs">
    <dtd publicId="-//OASIS//DTD DocBook XML V4.1.2//EN"
         location="docbook/docbookx.dtd"/>
    <dtd publicId="-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
         location="web-app_2_2.dtd"/>
</xmlcatalog>

設定 XMLCatalog,其中包含 DTD 和實體的組合,以及巢狀的 XMLCatalog 和兩種格式的外部目錄檔

<xmlcatalog id="allcatalogs">
    <dtd publicId="-//ArielPartners//DTD XML Article V1.0//EN"
         location="com/arielpartners/knowledgebase/dtd/article.dtd"/>
    <entity publicId="LargeLogo"
            location="com/arielpartners/images/ariel-logo-large.gif"/>
    <xmlcatalog refid="commonDTDs"/>
        <catalogpath>
            <pathelement location="/etc/sgml/catalog"/>
            <fileset dir="/anetwork/drive"
                     includes="**/catalog"/>
            <fileset dir="/my/catalogs"
                     includes="**/catalog.xml"/>
        </catalogpath>
    </xmlcatalog>
</xmlcatalog>

xslt 工作中參照上述 XMLCatalog

<xslt basedir="${source.doc}"
      destdir="${dest.xdocs}"
      extension=".xml"
      style="${source.xsl.converter.docbook}"
      includes="**/*.xml"
      force="true">
    <xmlcatalog refid="allcatalogs"/>
</xslt>