All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.crabshue.commons.xslt.XsltExecutor Maven / Gradle / Ivy

package com.crabshue.commons.xslt;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

import com.crabshue.commons.exceptions.ApplicationException;
import com.crabshue.commons.exceptions.SystemException;
import com.crabshue.commons.file.FileSystemUtils;
import com.crabshue.commons.xml.inputsource.InputSourceBuilder;
import com.crabshue.commons.xslt.exceptions.XsltErrorContext;
import com.crabshue.commons.xslt.exceptions.XsltErrorType;
import lombok.NonNull;


/**
 * XSLT executor.
 */
public class XsltExecutor {

    private static final String FACTORY_CLASS_NAME = net.sf.saxon.TransformerFactoryImpl.class.getName();

    private static TransformerFactory factory = TransformerFactory.newInstance(FACTORY_CLASS_NAME, XsltExecutor.class.getClassLoader());

    private static Logger logger = LoggerFactory.getLogger(XsltExecutor.class);

    private URI xsltUri;

    private File xmlFile;

    private InputSource xmlInputSource;

    private File outputFile;

    private File workingFolder = new File(".");

    private Map parameters = new HashMap<>();

    private URIResolver uriResolver = null;

    private URIResolver transformerUriResolver = null;

    /**
     * Prepare an XSLT executor with a {@link URI XSLT URI}.
     *
     * @param xsltUri the XSLT URI.
     * @return instance.
     */
    public static XsltExecutor of(@NonNull final URI xsltUri) {

        final XsltExecutor ret = new XsltExecutor();
        ret.xsltUri = xsltUri;
        ret.uriResolver = new RelativeXsltUriResolver(ret.xsltUri);
        return ret;
    }

    /**
     * Prepare an XSLT executor with a {@link File XSLT file}.
     *
     * @param xsltFile the XSLT file.
     * @return instance.
     */
    public static XsltExecutor of(@NonNull final File xsltFile) {

        return of(xsltFile.toURI());
    }

    /**
     * Set the XML {@link File}.
     *
     * @param xmlFile the XML file.
     * @return instance.
     */
    public XsltExecutor withXmlFile(@NonNull final File xmlFile) {

        this.xmlFile = xmlFile;
        return this;
    }

    /**
     * Set the XML {@link InputSource}.
     *
     * @param xmlInputSource the XML input source.
     * @return instance.
     */
    public XsltExecutor withXmlInputSource(@NonNull final InputSource xmlInputSource) {

        this.xmlInputSource = xmlInputSource;
        return this;
    }

    /**
     * Set the XML {@link Node}.
     *
     * @param xmlNode the XML input node.
     * @return instance.
     */
    public XsltExecutor withXmlNode(@NonNull final Node xmlNode) {

        this.xmlInputSource = InputSourceBuilder.newInputSource(xmlNode);
        return this;
    }

    /**
     * Set the output {@link File}.
     *
     * @param outputFile the output file.
     * @return instance
     */
    public XsltExecutor withOutputFile(@NonNull final File outputFile) {

        this.outputFile = outputFile;
        return this;
    }

    /**
     * Set the working {@link File folder} for the XSLT execution.
     * 

Default value is {@code new File("."}

* * @param workingFolder the working folder. * @return instance. */ public XsltExecutor withWorkingFolder(@NonNull final File workingFolder) { this.workingFolder = workingFolder; return this; } /** * Set parameters map for the XSLT execution. * * @param parameters the parameters. * @return instance. */ public XsltExecutor withParameters(@NonNull final Map parameters) { this.parameters.clear(); this.parameters.putAll(parameters); return this; } /** * Add parameter for the XSLT execution. * * @param name the parameter name. * @param value the parameter value. * @return instance. */ public XsltExecutor withParameter(@NonNull final String name, @NonNull final String value) { this.parameters.put(name, value); return this; } /** * Set the XSLT factory URI resolver to use during the XSLT compilation. * * @param uriResolver the URI resolver. * @return instance. */ public XsltExecutor withUriResolver(@NonNull final URIResolver uriResolver) { this.uriResolver = uriResolver; return this; } /** * Set the XSLT transformer URI resolver to use during the XSLT execution. * * @param transformerUriResolver the URI resolver. * @return instance. */ public XsltExecutor withTransformerUriResolver(@NonNull final URIResolver transformerUriResolver) { this.transformerUriResolver = transformerUriResolver; return this; } /** * Execute the XSLT stylesheet. * * @return the output file. */ public File execute() { FileSystemUtils.provideFolder(outputFile.getParentFile()); try { final Transformer xsltTransformer = newTransformer(); Optional.ofNullable(this.transformerUriResolver) .ifPresent(xsltTransformer::setURIResolver); // passing parameters parameters.forEach(xsltTransformer::setParameter); final String backupWorkingDirectory = System.getProperty("user.dir"); System.setProperty("user.dir", workingFolder.getAbsolutePath()); try (InputStream is = resolveInputStream(); OutputStream os = new FileOutputStream(outputFile)) { // Prepare the input and output files final Source source = new StreamSource(is); final Result result = new StreamResult(os); // Apply the xsl file to the source file and write the result to the output file xsltTransformer.transform(source, result); } finally { System.setProperty("user.dir", backupWorkingDirectory); } logger.info("Applied XSLT conversion [{}] on input file [{}] with output file [{}]", xsltUri, xmlFile, outputFile); return outputFile; } catch (IOException | TransformerException e) { throw new ApplicationException(XsltErrorType.ERROR_APPLYING_XSLT, e) .addContextValue(XsltErrorContext.XSLT, xsltUri) .addContextValue(XsltErrorContext.XML, xmlFile) .addContextValue(XsltErrorContext.OUTPUT, outputFile); } } /** * Build input stream on one of the possible input sources (xml file, input source). * * @return the input stream. */ private InputStream resolveInputStream() { final InputStream ret; // open input stream on xml file if (Objects.nonNull(this.xmlFile)) { try { if (!this.xmlFile.exists()) { throw new ApplicationException(XsltErrorType.XML_FILE_DOES_NOT_EXIST) .addContextValue(XsltErrorContext.XML, this.xmlFile); } ret = new FileInputStream(this.xmlFile); } catch (FileNotFoundException e) { throw new SystemException(XsltErrorType.ERROR_OPENING_STREAM_ON_XML_FILE, e) .addContextValue(XsltErrorContext.XML, this.xmlFile); } } // open input stream on input source else if (Objects.nonNull(this.xmlInputSource)) { ret = this.xmlInputSource.getByteStream(); } else { throw new ApplicationException(XsltErrorType.NO_XML_INPUT); } return ret; } private Transformer newTransformer() { // resolve xslt includes factory.setURIResolver(uriResolver); // Use the factory to create a template containing the xsl file final Transformer xsltTransformer; try { final Templates template = factory.newTemplates(new StreamSource(xsltUri.toURL().openStream())); xsltTransformer = template.newTransformer(); } catch (TransformerConfigurationException e) { throw new SystemException(XsltErrorType.ERROR_APPLYING_XSLT, e); } catch (IOException e) { throw new ApplicationException(XsltErrorType.ERROR_FINDING_XSLT, e) .addContextValue(XsltErrorContext.XSLT, xsltUri); } return xsltTransformer; } private XsltExecutor() { } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy