xml-commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Craeg Strong <vze2r...@verizon.net>
Subject Re: Resolver Library and Ant Task
Date Wed, 13 Nov 2002 21:44:36 GMT
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


Mime
View raw message