开发者

Using an XML Catalog with a Java library that uses JAXP internally

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.

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 bein开发者_开发百科g 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?


I think you want the system property xml.catalog.files.

Take a look at http://xml.apache.org/commons/components/resolver/resolver-article.html

BTW, this was the third hit on a Google search for jaxp catalog


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.

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);

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜