将XML目录与在内部使用JAXP的Java库一起使用

时间:2010-06-18 07:00:06

标签: java xml catalog

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

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

2 个答案:

答案 0 :(得分:1)

我认为您需要系统属性xml.catalog.files

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

顺便说一句,这是谷歌搜索jaxp catalog

的第三次打击

答案 1 :(得分: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对象,您可以使用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