使用带有内部使用 JAXP 的 Java 库的 XML 目录 [英] Using an XML Catalog with a Java library that uses JAXP internally

查看:22
本文介绍了使用带有内部使用 JAXP 的 Java 库的 XML 目录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using the Apache web service xml rpc library to make requests to an rpc service. Somewhere in that process is a xml document with a DTD reference to http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd, which the library attempts to download when parsing the XML. That download fails with a 503 status code because the w3c is blocking repeated downloads of this largely static document from Java clients.

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

The solution is XML Catalogs to locally cache the DTD. However, while I can find examples of setting an EntityHandler on a JAXP SAXParser instance directly to enable catalog parser support, I don't actually have access to the underlying parser here. It's just being used by the xml rpc library. Is there any way I can set a global property or something that will tell JAXP to use XML catalogs?

推荐答案

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

Unfortunately, setting xml.catalog.files does NOT have any effect on the parser factory. Ideally it should, of course, but the only way to use a resolver is to somehow add a method that delegates resolution to the catalog resolver in the handler that the SAX parser uses.

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

If you are already using a SAX parser, that's pretty easy:

 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 对象,你不能但你可以使用诡计:

Otherwise, you'll need to figure out if you can supply your own entity resolver. With a javax.xml.parsers.DocumentBuilder, you can. With the scala.xml.XML object, you can't but you can use subterfuge:

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

这篇关于使用带有内部使用 JAXP 的 Java 库的 XML 目录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆