7

我正在使用 Apache Web 服务 xml rpc 库向 rpc 服务发出请求。在该过程中的某处是一个 xml 文档,其中包含对http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd的 DTD 引用,该库在解析 XML 时尝试下载该文档。该下载失败并显示 503 状态代码,因为 w3c 正在阻止从 Java 客户端重复下载这个基本上是静态的文档。

解决方案是在本地缓存 DTD 的 XML 目录。但是,虽然我可以找到直接在 JAXP SAXParser 实例上设置 EntityHandler 以启用目录解析器支持的示例,但我实际上无法访问此处的底层解析器。它只是被 xml rpc 库使用。有什么方法可以设置全局属性或告诉 JAXP 使用 XML 目录的东西吗?

4

2 回答 2

1

不幸的是,设置 xml.catalog.files 对解析器工厂没有任何影响。理想情况下当然应该这样做,但使用解析器的唯一方法是以某种方式添加一个方法,该方法将解析委托给 SAX 解析器使用的处理程序中的目录解析器。

如果您已经在使用 SAX 解析器,那非常简单:

 final CatalogResolver catalogResolver = new CatalogResolver();
  DefaultHandler handler = new DefaultHandler() {
        public InputSource resolveEntity (String publicId, String systemId) {
            return catalogResolver.resolveEntity(publicId, systemId);
        }
        public void startElement(String namespaceURI, String lname, String qname,
           Attributes attrs) { 
           // the stuff you'd normally do
        }
        ...
     };

  SAXParserFactory factory = SAXParserFactory.newInstance();
  factory.setNamespaceAware(true);
  SAXParser saxParser = factory.newSAXParser();
  String url = args.length == 0 ? "http://horstmann.com/index.html" : args[0];
  saxParser.parse(new URL(url).openStream(), handler);

否则,您需要确定是否可以提供自己的实体解析器。使用 javax.xml.parsers.DocumentBuilder,您可以。使用 scala.xml.XML 对象,你不能,但你可以使用诡计:

val res = new com.sun.org.apache.xml.internal.resolver.tools.CatalogResolver

val loader = new factory.XMLLoader[Elem] {
  override def adapter = new parsing.NoBindingFactoryAdapter() {
    override def resolveEntity(publicId: String, systemId: String) = {
      res.resolveEntity(publicId, systemId) 
    }
  }
}

val doc = loader.load(new URL("http://horstmann.com/index.html"))enter code here
于 2011-12-13T17:34:25.943 回答
1

我想你想要系统属性xml.catalog.files

看看http://xml.apache.org/commons/components/resolver/resolver-article.html

顺便说一句,这是谷歌搜索的第三次点击jaxp catalog

于 2010-06-18T15:38:43.600 回答