XMLCatalog 是一个公共资源目录,例如 XML 文档中引用的 DTD 或实体。目录通常用于使对资源的 Web 引用指向资源的本地缓存副本。
这允许 XML 解析器、XSLT 处理器或其他 XML 文档使用者有效地允许对 Web 上可用的资源进行本地替换。
注意:此任务使用但并不依赖于 Apache Ant 分发版中未包含的外部库。有关更多信息,请参见 库依赖项。
此数据类型根据 OASIS XML Catalog 标准 提供资源位置目录。目录条目用于实体解析和 URI 解析,符合 org.xml.sax.EntityResolver
和 javax.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,以验证文档。
这在构建过程中可能非常耗时,尤其是在网络吞吐量有限的情况下。或者,您可以执行以下操作
<xmlcatalog>
,其中包含一个 <dtd>
元素,其 location 属性指向该文件。XMLCatalog 可以出现在支持此功能的任务内部,也可以出现在与 target
相同的级别上,即作为 project
的子级,以便在不同的任务中重复使用,例如 XML 验证和 XSLT 转换。XML 验证任务使用 XMLCatalog 进行实体解析。XSLT 转换任务使用 XMLCatalog 进行实体和 URI 解析。
XMLCatalog 指定为对构建文件中先前定义的另一个 XMLCatalog 的引用,或作为 dtd
或 entity
位置列表。此外,外部目录文件可以在嵌套的 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 目录条目类型 PUBLIC
和 URI
。相比之下,外部目录文件可以使用 OASIS 规范 中定义的任何条目类型。
当 XML 处理器查找实体、DTD 或 URI 时,XMLCatalog 会搜索其条目列表以查看是否有任何匹配项。也就是说,它尝试将每个条目的 publicId 属性与要解析的实体的 PublicID 或 URI 进行匹配。假设找到了匹配的条目,XMLCatalog 然后执行以下步骤
首先在文件系统中查找 location。如果 location 是相对路径,则 Ant 项目 basedir 属性用作基目录。如果 location 指定绝对路径,则按原样使用。一旦我们获得了绝对路径,我们就检查该路径是否存在有效且可读的文件。如果是,我们就完成了。如果不是,我们继续执行下一步。
接下来在类路径中查找 location。请记住,jar 文件只是花哨的 zip 文件。对于类路径查找,location 按原样使用(不附加任何基目录)。我们使用 Classloader 尝试从类路径加载资源。例如,如果 hello.jar 位于类路径中,并且它包含 foo/bar/blat.dtd,它将解析 location 为 foo/bar/blat.dtd 的实体。当然,它不会解析 location 为 blat.dtd
的实体。
接下来发生的事情取决于类路径上是否存在来自 xml-commons 的解析器库。如果是,我们将所有进一步的解析尝试推迟到它。解析器库支持非常复杂的功能,例如 URL 重写等,可以通过在外部目录文件中进行适当的条目来访问这些功能(XMLCatalog 尚未为 OASIS 标准 中定义的所有条目提供内联支持)。
最后,我们尝试从 location 创建一个 URL。起初,这似乎会违背 XMLCatalog 的目的——为什么要回到互联网?但实际上,这可以用来(从某种意义上说)实现 HTTP 重定向,将一个 URL 替换为另一个 URL。映射到的 URL 也可能由本地 Web 服务器提供服务。如果 URL 解析为有效且可读的资源,我们就完成了。否则,我们放弃。在这种情况下,XML 处理器将执行其正常的解析算法。根据处理器的配置,进一步的解析失败可能会或可能不会导致致命(即构建结束)错误。
属性 | 描述 | 必需 |
---|---|---|
id | XMLCatalog 的唯一名称,用于从另一个 XMLCatalog 引用 XMLCatalog 的内容 | 否 |
refid | 另一个 XMLCatalog 的 id,您希望将该 XMLCatalog 的内容用于此 XMLCatalog | 否 |
用于指定 XMLCatalog 的 dtd
和 entity
元素在结构上是相同的
属性 | 描述 | 必需 |
---|---|---|
publicId | 定义 dtd 或实体时使用的公共标识符,例如 "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" |
是 |
location | 要用于指定公共标识符的本地替换的位置。这可以指定为文件名、类路径上找到的资源名称或 URL。相对路径将根据基目录解析,默认情况下为 Ant 项目 basedir。 | 是 |
用于 实体解析 的类路径。嵌套的 <classpath>
是一个类似于 路径 的结构。
嵌套的 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>