diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/XsltPayloadTransformer.java b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/XsltPayloadTransformer.java index ba16447f90..a156c975d9 100644 --- a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/XsltPayloadTransformer.java +++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/XsltPayloadTransformer.java @@ -39,146 +39,158 @@ import org.springframework.util.Assert; import org.springframework.xml.transform.StringResult; import org.springframework.xml.transform.StringSource; +import java.io.IOException; + /** * Thread safe XSLT transformer implementation which returns a transformed {@link Source}, * {@link Document}, or {@link String}. If alwaysUseSourceResultFactories is * false (default) the following logic occurs - * + *

* {@link String} payload in results in {@link String} payload out - * + *

* {@link Document} payload in {@link Document} payload out - * + *

* {@link Source} payload in {@link Result} payload out, type will be determined * by the {@link ResultFactory}, {@link DomResultFactory} by default. If an * instance of {@link ResultTransformer} is registered this will be used to * convert the result. - * + *

* If alwaysUseSourceResultFactories is true then the ResultFactory and * {@link SourceFactory} will be used to create the {@link Source} from the * payload and the {@link Result} to pass into the transformer. An instance of * {@link ResultTransformer} can also be provided to convert the Result prior to * returning - * - * + * * @author Jonas Partner * @author Mark Fisher */ public class XsltPayloadTransformer extends AbstractPayloadTransformer { - private final Templates templates; + private final Templates templates; - private final ResultTransformer resultTransformer; + private final ResultTransformer resultTransformer; - private volatile SourceFactory sourceFactory = new DomSourceFactory(); + private volatile SourceFactory sourceFactory = new DomSourceFactory(); - private volatile ResultFactory resultFactory = new DomResultFactory(); + private volatile ResultFactory resultFactory = new DomResultFactory(); - private volatile boolean alwaysUseSourceResultFactories = false; + private volatile boolean alwaysUseSourceResultFactories = false; - public XsltPayloadTransformer(Templates templates) throws ParserConfigurationException { - this(templates, null); - } + public XsltPayloadTransformer(Templates templates) throws ParserConfigurationException { + this(templates, null); + } - public XsltPayloadTransformer(Templates templates, - ResultTransformer resultTransformer) - throws ParserConfigurationException { - this.templates = templates; - this.resultTransformer = resultTransformer; - } + public XsltPayloadTransformer(Templates templates, + ResultTransformer resultTransformer) + throws ParserConfigurationException { + this.templates = templates; + this.resultTransformer = resultTransformer; + } - public XsltPayloadTransformer(Resource xslResource) throws Exception { - this(TransformerFactory.newInstance().newTemplates( - new StreamSource(xslResource.getInputStream())),null); - } + public XsltPayloadTransformer(Resource xslResource) throws Exception { + this(TransformerFactory.newInstance().newTemplates( + createStreamSourceOnResource(xslResource)), null); + } - public XsltPayloadTransformer(Resource xslResource, ResultTransformer resultTransformer) throws Exception { - this(TransformerFactory.newInstance().newTemplates( - new StreamSource(xslResource.getInputStream())),resultTransformer); - } + public XsltPayloadTransformer(Resource xslResource, ResultTransformer resultTransformer) throws Exception { + this(TransformerFactory.newInstance().newTemplates( + createStreamSourceOnResource(xslResource)), resultTransformer); + } + + /** + * Compensate for the fact that a Resource may not be a File or even addressable through a URI. + * If it is, we want the created StreamSource to read other resources relative to the provided one, if it + * isn't, it loads from the default path. + */ + private static StreamSource createStreamSourceOnResource(Resource xslResource) throws IOException { + try { + String systemId = xslResource.getURI().toString(); + return new StreamSource(xslResource.getInputStream(), systemId); + } catch (IOException e) { + return new StreamSource(xslResource.getInputStream()); + } + } - /** - * @param sourceFactory - */ - public void setSourceFactory(SourceFactory sourceFactory) { - Assert.notNull(sourceFactory, "SourceFactory can not be null"); - this.sourceFactory = sourceFactory; - } + /** + * @param sourceFactory + */ + public void setSourceFactory(SourceFactory sourceFactory) { + Assert.notNull(sourceFactory, "SourceFactory can not be null"); + this.sourceFactory = sourceFactory; + } - /** - * @param resultFactory - */ - public void setResultFactory(ResultFactory resultFactory) { - Assert.notNull(sourceFactory, "ResultFactory can not be null"); - this.resultFactory = resultFactory; - } + /** + * @param resultFactory + */ + public void setResultFactory(ResultFactory resultFactory) { + Assert.notNull(sourceFactory, "ResultFactory can not be null"); + this.resultFactory = resultFactory; + } - /** - * Forces use of {@link ResultFactory} and {@link SourceFactory} even for - * directly supported payloads such as {@link String} and {@link Document} - * - * @param alwaysUserSourceResultFactories - */ - public void setAlwaysUseSourceResultFactories( - boolean alwaysUserSourceResultFactories) { - this.alwaysUseSourceResultFactories = alwaysUserSourceResultFactories; - } + /** + * Forces use of {@link ResultFactory} and {@link SourceFactory} even for + * directly supported payloads such as {@link String} and {@link Document} + * + * @param alwaysUserSourceResultFactories + * + */ + public void setAlwaysUseSourceResultFactories( + boolean alwaysUserSourceResultFactories) { + this.alwaysUseSourceResultFactories = alwaysUserSourceResultFactories; + } - @Override - public Object transformPayload(Object payload) throws TransformerException { - Object transformedPayload = null; - if (this.alwaysUseSourceResultFactories) { - transformedPayload = transformUsingFactories(payload); - } - else if (payload instanceof String) { - transformedPayload = transformString((String) payload); - } - else if (payload instanceof Document) { - transformedPayload = transformDocument((Document) payload); - } - else if (payload instanceof Source) { - transformedPayload = transformSource((Source) payload, payload); - } - else { - // fall back to trying factories - transformedPayload = transformUsingFactories(payload); - } - return transformedPayload; - } + @Override + public Object transformPayload(Object payload) throws TransformerException { + Object transformedPayload = null; + if (this.alwaysUseSourceResultFactories) { + transformedPayload = transformUsingFactories(payload); + } else if (payload instanceof String) { + transformedPayload = transformString((String) payload); + } else if (payload instanceof Document) { + transformedPayload = transformDocument((Document) payload); + } else if (payload instanceof Source) { + transformedPayload = transformSource((Source) payload, payload); + } else { + // fall back to trying factories + transformedPayload = transformUsingFactories(payload); + } + return transformedPayload; + } - protected Object transformUsingFactories(Object payload) throws TransformerException { - Source source = sourceFactory.createSource(payload); - return transformSource(source, payload); - } + protected Object transformUsingFactories(Object payload) throws TransformerException { + Source source = sourceFactory.createSource(payload); + return transformSource(source, payload); + } - protected Object transformSource(Source source, Object payload) throws TransformerException { - Result result = resultFactory.createResult(payload); - this.templates.newTransformer().transform(source, result); + protected Object transformSource(Source source, Object payload) throws TransformerException { + Result result = resultFactory.createResult(payload); + this.templates.newTransformer().transform(source, result); - if (resultTransformer != null) { - return resultTransformer.transformResult(result); - } - return result; - } + if (resultTransformer != null) { + return resultTransformer.transformResult(result); + } + return result; + } - protected String transformString(String stringPayload) throws TransformerException { - StringResult result = new StringResult(); - this.templates.newTransformer().transform( - new StringSource(stringPayload), result); - return result.toString(); - } + protected String transformString(String stringPayload) throws TransformerException { + StringResult result = new StringResult(); + this.templates.newTransformer().transform( + new StringSource(stringPayload), result); + return result.toString(); + } - protected Document transformDocument(Document documentPayload) throws TransformerException { - DOMSource source = new DOMSource(documentPayload); - Result result = resultFactory.createResult(documentPayload); - if (!DOMResult.class.isAssignableFrom(result.getClass())) { - throw new MessagingException( - "Document to Document conversion requires a DOMResult-producing ResultFactory implementation"); - } - DOMResult domResult = (DOMResult) result; - this.templates.newTransformer().transform(source, domResult); - return (Document) domResult.getNode(); - } + protected Document transformDocument(Document documentPayload) throws TransformerException { + DOMSource source = new DOMSource(documentPayload); + Result result = resultFactory.createResult(documentPayload); + if (!DOMResult.class.isAssignableFrom(result.getClass())) { + throw new MessagingException( + "Document to Document conversion requires a DOMResult-producing ResultFactory implementation"); + } + DOMResult domResult = (DOMResult) result; + this.templates.newTransformer().transform(source, domResult); + return (Document) domResult.getNode(); + } } diff --git a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/XsltPayloadTransformerTests.java b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/XsltPayloadTransformerTests.java index 96407d09e9..7fe01c0977 100644 --- a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/XsltPayloadTransformerTests.java +++ b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/XsltPayloadTransformerTests.java @@ -26,13 +26,16 @@ import javax.xml.transform.dom.DOMResult; import org.junit.Before; import org.junit.Test; +import static org.junit.Assert.assertThat; import org.w3c.dom.Document; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.Resource; +import org.springframework.core.io.ClassPathResource; import org.springframework.integration.core.MessagingException; import org.springframework.integration.xml.util.XmlTestUtil; import org.springframework.xml.transform.StringSource; +import static org.hamcrest.CoreMatchers.is; /** * @author Jonas Partner @@ -113,6 +116,13 @@ public class XsltPayloadTransformerTests { transformer.transformPayload(new Long(12)); } + @Test + public void testXsltWithImports() throws Exception { + Resource resource = new ClassPathResource("transform-with-import.xsl", this.getClass()); + transformer = new XsltPayloadTransformer(resource); + assertThat(transformer.transformString(docAsString), is(outputAsString)); + } + private Resource getXslResource() throws Exception { String xsl = "test"; diff --git a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/transform-with-import.xsl b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/transform-with-import.xsl new file mode 100644 index 0000000000..1500b7a419 --- /dev/null +++ b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/transform-with-import.xsl @@ -0,0 +1,5 @@ + + + + + diff --git a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/transform.xsl b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/transform.xsl new file mode 100644 index 0000000000..c81165b217 --- /dev/null +++ b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/transform.xsl @@ -0,0 +1,7 @@ + + + + test + + +