Project

Profile

Help

Trying to use catalog resolver

Added by ian davis over 9 years ago

This is I suspect a mostly don't know what I am doing question, but how do I attach a catalog resolver to a processor in 9.5PE .net? I am not sure of how much you need to see, so I have tried to pick out the bits that I think affect what I am trying to do.

imports of: using Saxon.Api; using net.sf.saxon; using net.sf.saxon.trans; using org.apache.xml.resolver.tools;

Then create the processor and read a document.

public void run(string filename) { string filepath = Path.GetDirectoryName(Path.GetFullPath(filename)); Uri baseDir = new Uri(filepath); Processor proc = new Processor(); proc.SetProperty("http://saxon.sf.net/feature/uriResolverClass", "org.apache.xml.resolver.tools.CatalogResolver"); net.sf.saxon.trans.XmlCatalogResolver.setCatalog("resources/dtd/catalog-dita.xml", proc.Implementation, true); DocumentBuilder builder = proc.NewDocumentBuilder(); builder.BaseUri = new Uri(filepath); builder.DtdValidation = false; XdmNode rootNode = builder.Build(new Uri(Path.GetFullPath(filename))); Console.Write(rootNode.ToString()); }

which when a document is read results in:

Cannot find CatalogManager.properties

Unhandled Exception: javax.xml.parsers.FactoryConfigurationError: Provider com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl not found at java.lang.Class.newInstance0(CallerID ) at java.lang.Class.newInstance(CallerID ) at net.sf.saxon.trans.DynamicLoader.getInstance(String className, PrintStream traceOut, ClassLoader classLoader) at net.sf.saxon.Configuration.getInstance(String className, ClassLoader classLoader) at net.sf.saxon.Configuration.instantiateClassName(String propertyName, Object value, Class requiredClass) at net.sf.saxon.Configuration.setConfigurationProperty(String name, Object value) at com.saxonica.config.ProfessionalConfiguration.setConfigurationProperty(String name, Object value) at Saxon.Api.Processor.SetProperty(String name, String value)

So, clearly doing something wrong but do not know what. And why com.sun...SAXParser... I thought that had been removed from Java as org.apache.xerces.jaxp.SAXParserFactoryImpl was available and a the less buggy implementation?


Replies (17)

Please register to reply

RE: Trying to use catalog resolver - Added by Michael Kay over 9 years ago

I'm not sure we actually have a test case for using catalogs on .NET via the API, as distinct from the command line, so we'll have to look into this.

If you use the option -catalog:filename on the command line, what Saxon does internally is to call the method

XmlCatalogResolver.setCatalog(String catalog, Configuration config, boolean isTracing)

and this sets all the required system properties, as well as setting org.apache.xml.resolver.tools.ResolvingXMLReader to be the selected sourceParser and styleParser in the specified Configuration.

So you seem to be going about this the right way.

You shouldn't need the call on setProperty to set the URIResolver, because the setCatalog method does this internally.

You say the exception occurs "when a document is read" - is there more stack trace identifying what your application is doing at the point where the exception occurs?

I can't see why the sun parser is being loaded. The setCatalog() method explicitly calls

Configuration.getPlatform().setDefaultSAXParserFactory();

which on .NET should call

System.setProperty("javax.xml.parsers.SAXParserFactory", "org.apache.xerces.jaxp.SAXParserFactoryImpl");

which should ensure that when the catalog resolver asks for the platform default parser, it gets the Apache one.

We'll look into it.

RE: Trying to use catalog resolver - Added by Michael Kay over 9 years ago

Could you try reversing the order of these two lines?

proc.SetProperty("http://saxon.sf.net/feature/uriResolverClass", "org.apache.xml.resolver.tools.CatalogResolver"); net.sf.saxon.trans.XmlCatalogResolver.setCatalog("resources/dtd/catalog-dita.xml", proc.Implementation, true);

I think it might be that the setProperty() is causing the catalog resolver to be initialized before the setCatalog() call gets a chance to set the relevant system properties that affect its behaviour.

Michael Kay Saxonica

RE: Trying to use catalog resolver - Added by ian davis over 9 years ago

Hi Mike

Thanks for the comments.

swapping the statements is one step forward, it is trying to find the correct version, but the error is the same

Unhandled Exception: javax.xml.parsers.FactoryConfigurationError: Provider org.apache.xerces.jaxp.SAXParserFactoryImpl not found at java.lang.Class.newInstance0(CallerID ) at java.lang.Class.newInstance(CallerID ) at net.sf.saxon.trans.DynamicLoader.getInstance(String className, ClassLoader classLoader) at net.sf.saxon.Configuration.makeURIResolver(String className) at net.sf.saxon.trans.XmlCatalogResolver.setCatalog(String catalog, Configuration config, Boolean isTracing)

After reading your comments I removed the setProperty as got the same response which as you suggest would indicate this is superfluous.

The rest of the stack would not shed much light I don't think it is the simple structure I have to get to the run() function above. at xmlManager.run(String filename) at Core.CoreMain..ctor() at pgMain.Main()

One further question. I have a PE license, but I do not think I am using the licensed version so I guess this would drop to HE. Is the functionality the same in both versions? (I have not set anything to pick up the license, do not have SAXON_HOME set, and have moved IKVM + saxon dlls into the VS output folder.)

RE: Trying to use catalog resolver - Added by T Hata about 9 years ago

Any update on this issue? I'm having the same exception on ASP.NET 4.0 + Saxon-EE 9.6.0.4.

RE: Trying to use catalog resolver - Added by T Hata about 9 years ago

My test code is pretty simple as ian's.


{
    Processor proc = new Processor();
    net.sf.saxon.trans.XmlCatalogResolver.setCatalog("http://example.com/catalog.xml", proc.Implementation, true);
    DocumentBuilder builder = proc.NewDocumentBuilder();
}

On ASP.NET:

[FactoryConfigurationError: Provider org.apache.xerces.jaxp.SAXParserFactoryImpl not found]
   IKVM.NativeCode.sun.misc.Unsafe.throwException(Object thisUnsafe, Exception x) +33
   sun.misc.Unsafe.throwException(Exception t) +37
   java.lang.Class.newInstance0(CallerID ) +744
   java.lang.Class.newInstance(CallerID ) +104
   net.sf.saxon.trans.DynamicLoader.getInstance(String className, ClassLoader classLoader) +180
   net.sf.saxon.Configuration.makeURIResolver(String className) +73
   net.sf.saxon.trans.XmlCatalogResolver.setCatalog(String catalog, Configuration config, Boolean isTracing) +237
   _Default.Page_Load(Object sender, EventArgs e)

For testing purposes, I copied the same code snippet into a console app Main(). The exception didn't happen at setCatalog(). But at NewDocumentBuilder() in the next line,

Unhandled Exception: System.InvalidCastException: Unable to cast object of type 'org.apache.xml.resolver.tools.CatalogResolver' to type 'net.sf.saxon.dotnet.DotNetURIResolver'.
   at Saxon.Api.Processor.get_XmlResolver()
   at Saxon.Api.Processor.NewDocumentBuilder()
   at ConsoleApplication1.Program.Main(String[] args)

I'm new to .NET and Saxon, so stuck here.

RE: Trying to use catalog resolver - Added by O'Neil Delpratt about 9 years ago

Hi thanks reporting the issue you have found. We are currently investigating it so we will respond shortly.

RE: Trying to use catalog resolver - Added by O'Neil Delpratt about 9 years ago

Hi,

I have managed to track down the cause to the problems reported.

In regards to the SAXParserFactoryImpl exception I have created the bug issue #2305 to keep track of the solution and reference The other problem relates to the class cast exception on the XmlResolver which has been detailed in the bug issue #2306.

RE: Trying to use catalog resolver - Added by O'Neil Delpratt about 9 years ago

Hi,

Just to say that both bugs have been fixed and committed to subversion. The patch will be available in the next maintenance release.

RE: Trying to use catalog resolver - Added by T Hata about 9 years ago

Really happy to hear that. Thank you, O'Neil.

RE: Trying to use catalog resolver - Added by ian davis about 9 years ago

Thanks very much O'Neil Do you have a release schedule at all, or is it keep a watch on the website?

On 04/02/2015 12:19, Saxonica Developer Community wrote:

RE: Trying to use catalog resolver - Added by O'Neil Delpratt about 9 years ago

Hi Ian,

We generally don't set firm deadlines. Nevertheless there are fair number of fixed bugs issues since the last maintenance, so we expect there to be another release soon. It might be good for you to subscribe as watcher to our releae announcements news at: https://saxonica.plan.io/news/1

Also we send notifications on the saxon mailing list:

RE: Trying to use catalog resolver - Added by T Hata about 9 years ago

On 9.6.0.5, the original exceptions do not happen. Thanks for the fix. However,

Uri uri = new Uri( "p:\\test.xsl" );
Processor proc = new Processor();
net.sf.saxon.trans.XmlCatalogResolver.setCatalog( "http://example.com/catalog.xml", proc.Implementation, true );
XsltCompiler compiler = proc.NewXsltCompiler();
XsltExecutable exec = compiler.Compile( uri );
ends up with another exception:
Unhandled Exception: System.InvalidCastException: Unable to cast object of type 'org.apache.xml.resolver.tools.CatalogResolver' to type 'net.sf.saxon.dotnet.DotNetURIResolver'.
   at Saxon.Api.XsltCompiler.get_XmlResolver()
   at Saxon.Api.XsltCompiler.Compile(Uri uri)
To get it work, do we need additional setProperty() or something?

RE: Trying to use catalog resolver - Added by O'Neil Delpratt almost 9 years ago

This is indeed a bug which has now been fixed and committed to subversion ready for the next maintenance release. See comment: https://saxonica.plan.io/issues/2306#note-6

As a workaround the following should work. Here we set a default XmlUrlResolver on the processor before the NewXsltCompiler method is called:

...
XmlUrlResolver resolver = new XmlUrlResolver;
proc.XmlResolver = resolver;

XsltCompiler compiler = proc.NewXsltCompiler();
...

RE: Trying to use catalog resolver - Added by T Hata almost 9 years ago

Thank you for fixing the underlying issue.

I'll try the workaround. Which one of the following presumptions is true?

  • With the workaround, the catalog resolver is expected to fully work.
  • The workaround only avoids the exception; the catalog resolver will not fully work until the next maintenance release.

RE: Trying to use catalog resolver - Added by Michael Kay almost 9 years ago

Sorry to drop the ball on this.

The workaround prevents the exception, but it does not enable the catalog resolver to be used on this path: at least not fully. To work fully, the resolver must handle both (a) XML-level references, e.g. to DTDs and external entities, and (b) XSLT-level references, e.g. xsl:include and xsl:import.

We've been studying the code, and it seems that:

  • Compile(Uri) always invokes the Microsoft .NET XMLReader. This will never under any circumstances use a catalog resolver to resolve XML-level references, but I think that once the exception is avoided, it may well use the catalog resolver to resolve XSLT-level references.

  • Compile(Stream) by contrast invokes the Apache XMLReader. This should work happily with the catalog resolver to resolve XML-level references.

We can't at present see any good reason why Compile(Uri) should not work in the same way as Compile(Stream). You might like to try using the latter interface, and seeing if this works.

RE: Trying to use catalog resolver - Added by T Hata almost 9 years ago

I modified my code to do setCatalog() and then Compile(Stream) instead of Compile(Uri)... Now the catalog resolver is working. Thank you so much!

    (1-17/17)

    Please register to reply