XMLCatalog

XMLCatalog 是一个公共资源目录,例如 XML 文档中引用的 DTD 或实体。目录通常用于使对资源的 Web 引用指向资源的本地缓存副本。

这允许 XML 解析器、XSLT 处理器或其他 XML 文档使用者有效地允许对 Web 上可用的资源进行本地替换。

注意:此任务使用但并不依赖于 Apache Ant 分发版中未包含的外部库。有关更多信息,请参见 库依赖项

此数据类型根据 OASIS XML Catalog 标准 提供资源位置目录。目录条目用于实体解析和 URI 解析,符合 org.xml.sax.EntityResolverjavax.xml.transform.URIResolver 接口,如 Java API for XML Processing (JAXP) 规范 中所定义。

例如,在 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">

没有 XMLCatalog 支持的 XML 处理器需要从指定的 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 也可能由本地 Web 服务器提供服务。如果 URL 解析为有效且可读的资源,我们就完成了。否则,我们放弃。在这种情况下,XML 处理器将执行其正常的解析算法。根据处理器的配置,进一步的解析失败可能会或可能不会导致致命(即构建结束)错误。

XMLCatalog 属性

属性 描述 必需
id XMLCatalog 的唯一名称,用于从另一个 XMLCatalog 引用 XMLCatalog 的内容
refid 另一个 XMLCatalog 的 id,您希望将该 XMLCatalog 的内容用于此 XMLCatalog

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,这些 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>