Hello: (see comments below)
Brian Smith wrote: > 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). Hmm. I am not sure if you are aware of it, but my patch that supports entity catalogs using the resolver library was just accepted into the Ant code base: http://cvs.apache.org/viewcvs.cgi/*checkout*/jakarta-ant/docs/manual/CoreTypes/xmlcatalog.html?rev=1.3&content-type=text/plain As you can see from the above, XMLCatalog now accepts both in-line and external file entries. I originally developed this code more than 6 months ago, just slightly too late for the 1.5 final release (by about two days :-( ) So it had to wait until 1.6. It is now in the 1.6 (alpha, not yet released) Ant codebase, obtainable via CVS snapshot or nightly build... > 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. Yes. I dealt with this problem in the same way Norm indicates: http://cvs.apache.org/viewcvs/jakarta-ant/src/main/org/apache/tools/ant/types/resolver/ApacheCatalogResolver.java?rev=1.3&content-type=text/vnd.viewcvs-markup public class ApacheCatalogResolver extends CatalogResolver { /** The XMLCatalog object to callback. */ private XMLCatalog xmlCatalog = null; static { // // If you don't do this, you get all sorts of annoying // warnings about a missing properties file. However, it // seems to work just fine with default values. Ultimately, // we should probably include a "CatalogManager.properties" // file in the ant jarfile with some default property // settings. See CatalogManager.java for more details. // CatalogManager.ignoreMissingProperties(true); // // Make sure CatalogResolver instantiates ApacheCatalog, // rather than a plain Catalog // System.setProperty("xml.catalog.className", ApacheCatalog.class.getName()); // debug // System.setProperty("xml.catalog.verbosity", "4"); } ...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 See Norm's reply.. I used the default catalog, as per his message... > (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). Not sure about this one. Are you talking about "nextCatalog" entries in the catalog files? > (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. Yes. I went through exactly the same learnings, made the appropriate fixes, and documented them in the code: http://cvs.apache.org/viewcvs.cgi/jakarta-ant/src/main/org/apache/tools/ant/types/XMLCatalog.java?rev=1.17&content-type=text/vnd.viewcvs-markup /** * <p>This is called from the URIResolver to set an EntityResolver * on the SAX parser to be used for new XML documents that are * encountered as a result of the document() function, xsl:import, * or xsl:include. This is done because the XSLT processor calls * out to the SAXParserFactory itself to create a new SAXParser to * parse the new document. The new parser does not automatically * inherit the EntityResolver of the original (although arguably * it should). See below:</p> * * <tt>"If an application wants to set the ErrorHandler or * EntityResolver for an XMLReader used during a transformation, * it should use a URIResolver to return the SAXSource which * provides (with getXMLReader) a reference to the XMLReader"</tt> * * <p>...quoted from page 118 of the Java API for XML * Processing 1.1 specification</p> * */ private void setEntityResolver(SAXSource source) throws TransformerException { XMLReader reader = source.getXMLReader(); if (reader == null) { SAXParserFactory spFactory = SAXParserFactory.newInstance(); spFactory.setNamespaceAware(true); try { reader = spFactory.newSAXParser().getXMLReader(); } catch (ParserConfigurationException ex) { throw new TransformerException(ex); } catch (SAXException ex) { throw new TransformerException(ex); } } reader.setEntityResolver(this); source.setXMLReader(reader); } --Craeg > > > - Brian
