4

I need a way to interfere in writting xsl result documents to avoid writting them to file system. Right now my template is writting to a temporary directory, and then i zip that directory. I want to do that whitout writting to file system. I am using saxon procesor. A solution that is using just standard java libraries is perfered. Any suggestion is appreciated.

EDIT: I found this class for .net saxon api http://www.saxonica.com/documentation/dotnetdoc/Saxon/Api/IResultDocumentHandler.html I need something equivalent for java.

Sten
  • 162
  • 7

3 Answers3

4

You need to implement interface net.sf.saxon.OutputURIResolver
http://www.saxonica.com/documentation/javadoc/net/sf/saxon/lib/OutputURIResolver.html
You can redirect output in resolve method however you like. In my case this is how implemented class looks like.

public class ZipOutputURIReslover implements OutputURIResolver{

    private ZipOutputStream zipOut;

    public ZipOutputURIReslover(ZipOutputStream zipOut) {
        super();
        this.zipOut = zipOut;
    }

    public void close(Result arg0) throws TransformerException {
        try {
            zipOut.closeEntry();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Result resolve(String href, String base) throws TransformerException {
        try {
            zipOut.putNextEntry(new ZipEntry(href));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new StreamResult(zipOut);
    }
}

After this you need to register net.sf.saxon.OutputURIResolver to trasnformer factory.

ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream("file.zip"));
factory.setAttribute("http://saxon.sf.net/feature/outputURIResolver", new ZipOutputURIReslover(zipOut));

When you load your template and run transformation all xsl:result-documents will be written directly to zipOutputStream.

Answer was found here http://sourceforge.net/p/saxon/discussion/94027/thread/9ee79dea/#70a9/6fef

Sten
  • 162
  • 7
  • 1
    `factory.setAttribute("http://saxon.sf.net/feature/outputURIResolver", new ZipOutputURIReslover(zipOut));` can be actually replaced with: `transformer.getUnderlyingController().setOutputURIResolver(outputURIResolver);`, where `transformer` is an instance of `XsltTransformer` class. – shapiy Mar 01 '13 at 11:46
0

You can use new StreamResult(ByteArrayOutputStream()) to catch xslt output, if you don't want to write to files, and then you can save memory data from byte array to zip file using this approach In Java: How to zip file from byte[] array?

Community
  • 1
  • 1
Kerb
  • 1,138
  • 2
  • 20
  • 39
  • 1
    Problem is i dont need to catch xslt output from "transform" function. That output is allways empty document. I need to catch output stream of function that is called inside template. I need somehow to interfere with saxons handling of this template function and saxons handling of those output streams. File names are relevant, and i dont know how many result documents this template will produce. It depends on input xml document. – Sten Dec 25 '12 at 13:05
0

Note that recent versions of Saxon require that the href (URI) is unique. Thus the system ID of the stream in the output resolver must also be unique.

For example:

  1. Specify the result document href values in the stylesheet

    <xsl:result-document href="{$filename}" method="text">
    
  2. Create the output resolver

    public class ZipOutputURIReslover implements OutputURIResolver{
    
        private ZipOutputStream zipOut;
    
        public ZipOutputURIReslover(ZipOutputStream zipOut) {
            super();
            this.zipOut = zipOut;
        }
    
        public void close(Result arg0) throws TransformerException {
            try {
                zipOut.closeEntry();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public Result resolve(String href, String base) throws TransformerException {
            try {
                zipOut.putNextEntry(new ZipEntry(href));
            } catch (IOException e) {
                e.printStackTrace();
            }
            Result result = new StreamResult(zipOut);
            // Must ensure the stream is given a unique ID
            result.setSystemId(UUID.randomUUID().toString());
            return result;
        }
    }
    
  3. Attach the output resolver to the transformer

    ZipOutputURIResolver outputResolver = new ZipOutputURIResolver(outputStream);
    // Controller is the Saxon implementation of the JAXP Transformer
    ((Controller) transformer).setOutputURIResolver(outputResolver);
    
jparrpearson
  • 1
  • 1
  • 1