diff --git a/src/main/java/info/textgrid/services/aggregator/html/HTML.java b/src/main/java/info/textgrid/services/aggregator/html/HTML.java
index 44d76ac653b2a570e8724e9e6d064a414b588abb..a7eaf595d87a8fe157f0af044dc2b3c22766c0e5 100644
--- a/src/main/java/info/textgrid/services/aggregator/html/HTML.java
+++ b/src/main/java/info/textgrid/services/aggregator/html/HTML.java
@@ -20,6 +20,8 @@
 import java.net.URI;
 import java.net.URL;
 import java.text.MessageFormat;
+import java.util.concurrent.ExecutionException;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.servlet.ServletContext;
@@ -34,8 +36,6 @@
 import javax.ws.rs.core.StreamingOutput;
 import javax.xml.transform.stream.StreamSource;
 
-import org.apache.cxf.jaxrs.model.wadl.Description;
-
 import net.sf.saxon.s9api.Processor;
 import net.sf.saxon.s9api.QName;
 import net.sf.saxon.s9api.SaxonApiException;
@@ -44,6 +44,13 @@
 import net.sf.saxon.s9api.XsltExecutable;
 import net.sf.saxon.s9api.XsltTransformer;
 
+import org.apache.cxf.jaxrs.model.wadl.Description;
+
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.cache.RemovalListener;
+import com.google.common.cache.RemovalNotification;
 import com.google.common.io.FileBackedOutputStream;
 
 @Path("/html")
@@ -64,6 +71,8 @@ public class HTML {
 	@Context
 	private ServletContext servlet;
 
+	private LoadingCache<URI, XsltExecutable> stylesheets;
+
 	private XsltExecutable getToHtml() {
 		if (toHtml == null) {
 			try {
@@ -84,6 +93,38 @@ private XsltExecutable getToHtml() {
 	public HTML(final ITextGridRep repository) throws IOException {
 		this.repository = repository;
 		xsltProcessor = new Processor(false);
+		stylesheets = CacheBuilder.newBuilder().maximumSize(50).weakValues()
+				.removalListener(new RemovalListener<URI, XsltExecutable>() {
+
+					@Override
+					public void onRemoval(
+							final RemovalNotification<URI, XsltExecutable> notification) {
+						logger.info(MessageFormat
+								.format("Removed stylesheet {0} from cache, reason: {1}",
+										notification.getKey(),
+										notification.getCause()));
+					}
+				})
+.build(new CacheLoader<URI, XsltExecutable>() {
+
+					@Override
+					public XsltExecutable load(final URI url) throws Exception {
+						final XsltCompiler compiler = xsltProcessor
+								.newXsltCompiler();
+						try {
+							final XsltExecutable executable = compiler
+									.compile(new StreamSource(url.toString()));
+							logger.log(Level.INFO,
+									"Successfully loaded stylesheet {0}", url);
+							return executable;
+						} catch (final Exception e) {
+							logger.log(Level.SEVERE, MessageFormat.format(
+									"Failed to load stylesheet {0}", url), e);
+							throw e;
+						}
+					}
+				});
+
 	}
 
 	@GET
@@ -94,13 +135,14 @@ public StreamingOutput get(
 			@PathParam("object") final URI uri,
 			@Description("If given, an alternative XSLT stylesheet to use")
 			@QueryParam("stylesheet") final URI xsluri,
+			@Description("If true and a stylesheet has been given, force reloading the stylesheet, do not cache") @QueryParam("refreshStylesheet") final boolean refreshStylesheet,
 			@Description("Session ID to access protected resources")
 			@QueryParam("sid") final String sid,
 			@Description("URL of the CSS that should be referenced in the HTML that is created")
 			@QueryParam("css") final URI css) throws ObjectNotFoundFault,
 			MetadataParseFault, IoFault, AuthFault,
 			ProtocolNotImplementedFault, WebApplicationException, IOException,
-			SaxonApiException {
+			SaxonApiException, ExecutionException {
 		logger.fine("HTML called for root object: " + uri);
 
 		final TGCrudService crud = repository.getCRUDService();
@@ -129,7 +171,15 @@ public StreamingOutput get(
 			tei = repository.getContent(uri, sid);
 		}
 
-		final XsltTransformer transformer = getToHtml().load();
+		final XsltTransformer transformer;
+		if (xsluri == null || "".equals(xsluri)) {
+			transformer = getToHtml().load();
+		} else {
+			if (refreshStylesheet) {
+				stylesheets.refresh(xsluri);
+			}
+			transformer = stylesheets.get(xsluri).load();
+		}
 		transformer.setSource(new StreamSource(tei));
 		transformer.setParameter(new QName("graphicsURLPattern"),
 				new XdmAtomicValue(repository.getCRUDRestEndpoint()
@@ -148,8 +198,8 @@ public void write(final OutputStream output) throws IOException,
 				transformer.setDestination(xsltProcessor.newSerializer(output));
 				try {
 					transformer.transform();
-					logger.fine("Finished transformation to HTML for "
-							+ rootObject);
+					logger.info("Finished transformation to HTML for "
+ + uri);
 				} catch (final SaxonApiException e) {
 					throw new WebApplicationException(e);
 				}