phax / ph-schematron

Java Schematron library that supports XSLT and native application
Apache License 2.0
110 stars 36 forks source link

Enable Saxon trace listener #176

Closed SvenHaul closed 1 month ago

SvenHaul commented 1 month ago

ph-schematron-api/src/main/java/com/helger/schematron/saxon/SchematronTransformerFactory.java

A https://www.saxonica.com/html/documentation12/javadoc/net/sf/saxon/lib/TraceListener.html allows to get intermediate results of the transformation. The listener can easily be added to the Saxon configuration, for example in a Spring Boot application. However, the SchematronTransformerFactory always creates its own instance with no outside access to the configuration.

It would be nice to have a configuration setting to enable Feature.COMPILE_WITH_TRACING to true, and state my own implementation of the TraceListener.

My use case for this particular request is that complex rules using functions are often hard to understand. So I want to present intermediate (function) results to the user as additional explanation, and the trace listener would give me easy access to this.

phax commented 1 month ago

I added a static method SchematronTransformerFactory.setTransformerFactoryCustomizer (Consumer <TransformerFactory>) so that you can customize the created TransformerFactory to your needs. Hope that makes sense to you. Just apply the setting globally, before calling the first Schematron stuff.

SvenHaul commented 1 month ago

Wow, this was super fast. And it works like a charm, thanks a million.

For anyone also using this from Spring Boot:

  1. Create your net.sf.saxon.Configuration bean as usual in a @Configuration class
  2. Set Feature.COMPILE_WITH_TRACING to true
  3. Build your Saxon trace listener (extend XSLTTraceListener and override as you wish)
  4. In a @PostContruct init method that @DependsOn the Saxon config bean, obtain the net.sf.saxon.Configuration bean, and inject it into a
  5. TransformerFactoryConsumer class that implements Consumer, and then call
  6. SchematronTransformerFactory.setTransformerFactoryCustomizer with your consumer class
  7. In your consumer class, in method accept, cast TransformerFactory to net.sf.saxon.TransformerFactoryImpl and set the net.sf.saxon.Configuration from step 4