/* * Copyright 2001-2008 Geert Bevin (gbevin[remove] at uwyn dot com) * Licensed under the Apache License, Version 2.0 (the "License") * $Id: XsltExtension.java 3918 2008-04-14 17:35:35Z gbevin $ */ package com.uwyn.rife.template; import com.uwyn.rife.tools.ExceptionUtils; import java.io.IOException; import java.lang.reflect.Method; import java.util.logging.Logger; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.FactoryConfigurationError; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.ErrorListener; import javax.xml.transform.Result; import javax.xml.transform.TransformerException; import javax.xml.transform.dom.DOMResult; import org.apache.xalan.extensions.XSLProcessorContext; import org.apache.xalan.templates.ElemExtensionCall; import org.apache.xalan.transformer.TransformerImpl; import org.w3c.dom.Document; import org.w3c.dom.DocumentFragment; import org.xml.sax.ContentHandler; public class XsltExtension implements ErrorListener { public void fatalError(TransformerException exception) throws TransformerException { Logger.getLogger("com.uwyn.rife.template").severe(ExceptionUtils.getExceptionStackTrace(exception)); } public void error(TransformerException exception) throws TransformerException { Logger.getLogger("com.uwyn.rife.template").severe(ExceptionUtils.getExceptionStackTrace(exception)); } public void warning(TransformerException exception) throws TransformerException { Logger.getLogger("com.uwyn.rife.template").warning(ExceptionUtils.getExceptionStackTrace(exception)); } public void value(XSLProcessorContext context, ElemExtensionCall element) throws FactoryConfigurationError, IOException, ParserConfigurationException, TransformerException { // ensure that the name of the tag has been provided String name = element.getAttribute("name"); if (null == name) { return; } // build a document for constructing the alternate output elements DocumentBuilderFactory factory = null; DocumentBuilder builder = null; Document document = null; factory = DocumentBuilderFactory.newInstance(); factory.setValidating(false); factory.setIgnoringComments(false); builder = factory.newDocumentBuilder(); document = builder.newDocument(); if (element.hasChildNodes()) { // create several document fragments to create the start and end tags DocumentFragment fragment_start = null; DocumentFragment fragment_children = null; DocumentFragment fragment_end = null; fragment_start = document.createDocumentFragment(); fragment_children = document.createDocumentFragment(); fragment_end = document.createDocumentFragment(); fragment_start.appendChild(document.createComment("V '"+name+"'")); fragment_end.appendChild(document.createComment("/V")); // process all child nodes and output the result to the middle // document fragment DOMResult children_result = null; TransformerImpl transformer = null; ContentHandler handler = null; children_result = new DOMResult(); children_result.setNode(fragment_children); transformer = context.getTransformer(); handler = createContentHandler(transformer, children_result); transformer.setErrorListener(this); transformer.executeChildTemplates(element, context.getContextNode(), context.getMode(), handler); // output the document fragments context.outputToResultTree(context.getStylesheet(), fragment_start); context.outputToResultTree(context.getStylesheet(), fragment_children); context.outputToResultTree(context.getStylesheet(), fragment_end); } else { // obtain a document fragment and add the correct comment to it // so that RIFE's template engine understands it DocumentFragment fragment_short = document.createDocumentFragment(); fragment_short.appendChild(document.createComment("V '"+name+"'/")); // output the document fragment context.outputToResultTree(context.getStylesheet(), fragment_short); } } private ContentHandler createContentHandler(TransformerImpl transformer, DOMResult childrenResult) throws TransformerException { ContentHandler handler = null; // support ibm and sun jdk which both contain a different version of // xalan try { Method method = null; try { method = transformer.getClass().getMethod("createResultContentHandler", Result.class); } catch (NoSuchMethodException e) { try { method = transformer.getClass().getMethod("createSerializationHandler", Result.class); } catch (NoSuchMethodException e2) { throw new TransformerException(e); } } handler = (ContentHandler)method.invoke(transformer, childrenResult); } catch (Exception e) { throw new TransformerException(e); } return handler; } public void block(XSLProcessorContext context, ElemExtensionCall element) throws FactoryConfigurationError, IOException, ParserConfigurationException, TransformerException { block("B", context, element); } public void blockvalue(XSLProcessorContext context, ElemExtensionCall element) throws FactoryConfigurationError, IOException, ParserConfigurationException, TransformerException { block("BV", context, element); } private void block(String tagName, XSLProcessorContext context, ElemExtensionCall element) throws FactoryConfigurationError, IOException, ParserConfigurationException, TransformerException { // ensure that the name of the tag has been provided String name = element.getAttribute("name"); if (null == name) { return; } // build a document for constructing the alternate output elements DocumentBuilderFactory factory = null; DocumentBuilder builder = null; Document document = null; factory = DocumentBuilderFactory.newInstance(); factory.setValidating(false); factory.setIgnoringComments(false); builder = factory.newDocumentBuilder(); document = builder.newDocument(); // create several document fragments to create the start and end tags DocumentFragment fragment_start = null; DocumentFragment fragment_end = null; fragment_start = document.createDocumentFragment(); fragment_end = document.createDocumentFragment(); fragment_start.appendChild(document.createComment(tagName+" '"+name+"'")); fragment_end.appendChild(document.createComment("/"+tagName)); // output the start tag document fragment context.outputToResultTree(context.getStylesheet(), fragment_start); if (element.hasChildNodes()) { // if there are child nodes, create a middle document fragment DOMResult children_result = new DOMResult(); DocumentFragment fragment_children = null; fragment_children = document.createDocumentFragment(); children_result.setNode(fragment_children); // process all child nodes and output the result to the middle // document fragment TransformerImpl transformer = context.getTransformer(); ContentHandler handler = createContentHandler(transformer, children_result); transformer.setErrorListener(this); transformer.executeChildTemplates(element, context.getContextNode(), context.getMode(), handler); // output the middle document fragment context.outputToResultTree(context.getStylesheet(), fragment_children); } // output the end tag document fragment context.outputToResultTree(context.getStylesheet(), fragment_end); } public void include(XSLProcessorContext context, ElemExtensionCall element) throws FactoryConfigurationError, IOException, ParserConfigurationException, TransformerException { // ensure that the name of the tag has been provided String name = element.getAttribute("name"); if (null == name) { return; } // build a document for constructing the alternate output elements DocumentBuilderFactory factory = null; DocumentBuilder builder = null; Document document = null; factory = DocumentBuilderFactory.newInstance(); factory.setValidating(false); factory.setIgnoringComments(false); builder = factory.newDocumentBuilder(); document = builder.newDocument(); // obtain a document fragment and add the correct comment to it // so that RIFE's template engine understands it DocumentFragment fragment = document.createDocumentFragment(); fragment.appendChild(document.createComment("I '"+name+"'/")); // output the document fragment context.outputToResultTree(context.getStylesheet(), fragment); } }