Hi,
I created an Ant task that is very similar to the current <style> task except that it uses the XML-Commons resolver library instead of the <xmlcatalog> Ant type (among other things). You use it like this:
<catalogset>
<catalog file="doc/smt.cat"/>
<catalog file="lib/xhtml.cat"/>
</catalogset>where doc/smt.cat is an OASIS XML Catalog and xhtml.cat is the TR??? catalog that comes with the XHTML 1.1 spec download. There is no support for specifying any part of the catalog inside the build file; all catalogs must be in external files. The rationale is that if you put your catalogs inside the build script, you cannot share them with other tools like NetBeans that can make use of them.
It seems to work well for my (simple) use cases. I am using CatalogResolver as the entity/URI resolver for the transformation. I have noticed the following issues and I would like to know how I can solve them:
(1) The CatalogResolver repeatedly prints out "Cannot find CatalogManager.properties" even when I am using a private catalog. It seems that the only way to shut this warning off is to set a system property or include a catalog.properties file in the classpath. I don't think that either of these things is a good thing for an Ant task to do. I need some way to tell the Catalog library not to output any messages, not to use any system catalogs, etc. without setting any system properties, etc.
(2) In general, it would be very good if the library worked in such a way that the system properties/catalogs were only used if they were explicitly designated to be used. For example, it seems like there could be a single instance of Catalog that represents all the system catalog files, and any application that wants to use the system catalog files would create the proper entry in their own catalog that delegates to this (shared) system catalog. For example (see below too):
ResolvingXMLReader reader = new ResolvingXMLReader();
// The reader's catalog is empty
reader.getCatalog().addCatalog(Catalog.getSystemCatalog());
// Now the reader has access to the system catalog
(3) I have found that I would like to have an instance of Catalog delegate to another instance of Catalog. Currently, this doesn't seem to be possible without subclassing. The idea is to group sets of catalogs together in different configurations, such that each catalog file is only read once, like this:
Catalog a = new Catalog();
a.parseCatalog(someFile);
a.parseCatalog(someOtherFile);
Catalog b = new Catalog();
b.parseCatalog(yetAnotherFile);
b.addCatalog(a); // b will now delegate to a as ncessary
The current mechanism seems to require that the catalog files must be parsed for each catalog they belong to (i.e. "someFile" and "someOtherFile" would have to be parsed twice in the above example).
(4) CatalogResolver works fine, but you have to be careful when using the document() function in XSLT. The XSLT engine isn't guarenteed to use the same entity resolver that it uses for the main document. I had to subclass it like this:
final XMLReader reader = XMLReaderFactory.createXMLReader();
CatalogResolver resolver = new CatalogResolver(true) {
public Source resolve(String base, String href)
throws TransformerException {
SAXSource result = (SAXSource) super.resolve(base, href);
result.setXMLReader(reader);
return result;
}
}In other words, I make sure that all documents use the same XMLReader so that they will use the same EntityResolver.
- Brian
