Re: How to get xsl:output/@method after transformation?

John Ulric <[email protected]> Sun, 2 May 2021 23:01:08 +0200
Newsgroups gmane.text.xml.saxon.help
Message-ID <CANS5Rie=U+itibXRouaEOSoe-O_x2E=uYfic-FDZbLcQCLN6Ww@mail.gmail.com>
Michael, thank you so much for looking into this. Works like you said.

For the record, below I've attached the code of how I've now packaged this.
This is somewhat, well … obscure. ;-) No offence intended. And I see no
easy way to avoid the ungainly ThreadLocal, except
wrapping/overriding/delegating the whole chain of
.newXsltCompiler()/XsltCompiler/.compile()/XsltExecutable/.load()/… up
until the Destination.

Would you consider adding a more official API for this? Should I file an
issue?

John


static class ProcessorCapturingOutputParams extends Processor {


    ProcessorCapturingOutputParams(final Configuration config) {
        super(withCapturing(config));
    }

    static Configuration withCapturing(Configuration configuration) {
        configuration.setSerializerFactory(new
SerializerFactoryCapturingOutputParams(configuration)); // todo: to be
safe, chain this with any existing serializer factory?
        return configuration;
    }

    public String getActualOutputMethod() {
        return lastProperties().map(p -> p.getProperty("method")).orElse(null);
    }

    public void clear() {
        ((SerializerFactoryCapturingOutputParams)
getUnderlyingConfiguration().getSerializerFactory()).lastProperties.remove();
    }

    private Optional<Properties> lastProperties() {
        return Optional.ofNullable(((SerializerFactoryCapturingOutputParams)
getUnderlyingConfiguration().getSerializerFactory()).lastProperties.get());
    }

    private static class SerializerFactoryCapturingOutputParams
extends SerializerFactory {

        private final ThreadLocal<Properties> lastProperties = new
ThreadLocal<>();

        private SerializerFactoryCapturingOutputParams(final
Configuration config) {
            super(config);
        }

        @Override
        public Receiver getReceiver(final Result result, final
SerializationProperties params, final PipelineConfiguration pipe)
throws XPathException {
            lastProperties.set(ofNullable(params.getProperties()).map(Properties::new).orElse(null));
            return super.getReceiver(result, params, pipe);
        }

    }

}




Am Sa., 1. Mai 2021 um 17:12 Uhr schrieb Michael Kay <mike-JkSD5nQpfvpWk0Htik3J/[email protected]>:

> Yes, I've looked at this in more detail, and it seems that when the
> decision between XML/XHTML/HTML serialization is delayed until the first
> element tag is output, the only way you can intercept this is by
> subclassing the SerializerFactory and nominating your subclass using
> Configuration.setSerializerFactory(). If you override the method
>
> public Receiver getReceiver(Result result,
>                             SerializationProperties params,
>                             PipelineConfiguration pipe)
>
> the first call will be with params that don't include a method. This call
> will therefore allocate an UncommittedSerializer. When the
> UncommittedSerializer gets a startElement() event it calls the
> SerializerFactory a second time, and on this occasion the params will
> include the selected method.
>
> Michael Kay
> Saxonica
>
>

_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[email protected]
https://lists.sourceforge.net/lists/listinfo/saxon-help