The XhiveTransformerIf and XhiveFormatterIf
interfaces in com.xhive.util.interfaces are really convenient
access methods to Xalan and FOP of Apache project respectively.
In some cases you may want to use the more advanced options of these packages.
This is why we give you our implementation of these interfaces here,
to give you a starting point on how to use the interfaces of those
packages.
import org.apache.fop.apps.Driver;
import org.apache.fop.apps.Version;
public void formatAsPDFToStream(Document foSource, OutputStream os) throws XhiveException {
try {
Driver driver = new Driver();
driver.setRenderer("org.apache.fop.render.pdf.PDFRenderer", Version.getVersion());
driver.addElementMapping("org.apache.fop.fo.StandardElementMapping");
driver.addElementMapping("org.apache.fop.svg.SVGElementMapping");
driver.addPropertyList("org.apache.fop.fo.StandardPropertyListMapping");
driver.addPropertyList("org.apache.fop.svg.SVGPropertyListMapping");
driver.setOutputStream(os);
driver.buildFOTree(foSource);
driver.format();
driver.render();
}
catch(Exception e) {
throw new XhiveException(XhiveException.FORMAT_EXCEPTION, e);
}
}
The sample code above is for a quite an old version (0.20) of FOP, shipped with
import org.apache.avalon.framework.logger.ConsoleLogger;
import org.apache.avalon.framework.logger.Logger;
import org.apache.fop.apps.Driver;
import org.apache.fop.messaging.MessageHandler;
public static void formatAsPDFToStream(DOMImplementation docCreator, Document xmlSource, Document xslSource, OutputStream os)
throws XhiveException {
try {
// XSLT part
XhiveTransformerIf transformer = XhiveDriverFactory.getDriver().getTransformer();
Document foDocument = transformer.transformToDocument(docCreator, xmlSource, xslSource);
// FOP part
Driver driver = new Driver();
Logger logger = new ConsoleLogger(ConsoleLogger.LEVEL_ERROR);
MessageHandler.setScreenLogger(logger);
driver.setLogger(logger);
driver.setRenderer(Driver.RENDER_PDF);
driver.setOutputStream(os);
driver.render(foDocument);
} catch (Exception e) {
//e.printStackTrace();
throw new XhiveException(XhiveException.FORMAT_EXCEPTION, e);
}
}
import com.xhive.core.interfaces.XhiveSessionIf;
import com.xhive.error.XhiveException;
import com.xhive.dom.*;
import org.w3c.dom.*;
import javax.xml.transform.*;
import java.io.*;
import java.util.Iterator;
public Document transformToDocument(DOMImplementation docCreator, Node xmlSource, Document xslSource)
throws XhiveException {
Document result = docCreator.createDocument("", "Result", null);
Node rootElem = result.getDocumentElement();
result.removeChild(rootElem);
transform(xmlSource, xslSource, new DOMResult(result));
return result;
}
public void transformToStream(Node xmlSource, Document xslSource, Writer writer)
throws XhiveException {
transform(xmlSource, xslSource, new StreamResult(writer));
}
public String transformToString(Node xmlSource, Document xslSource)
throws XhiveException {
StringWriter result = new StringWriter();
transformToStream(xmlSource, xslSource, result);
return result.toString();
}
private void transform(Node xmlSource, Document xslSource, Result result) {
try {
// Try to initialize URI resolver
URIResolver myResolver;
try {
XhiveSessionIf session = ...; // Left as an exercise to the reader
if (session != null) {
myResolver = new XhiveURIResolver(session);
} else {
myResolver = null;
}
} catch (Exception e) {
// (No session?) Fine, then we don't use a URIResolver
myResolver = null;
}
TransformerFactory tFactory = TransformerFactory.newInstance();
if (myResolver != null) {
// Factory resolver must be set before transformer is created
tFactory.setURIResolver(myResolver);
}
Transformer transformer = tFactory.newTransformer(new DOMSource(xslSource));
if (myResolver != null) {
transformer.setURIResolver(myResolver);
}
transformer.transform(new DOMSource(xmlSource), result);
} catch (Exception e) {
throw new XhiveException(XhiveException.TRANSFORM_EXCEPTION, e);
}
}
/**
* URI resolver that translates
* xhive:path#query
* into an xquery run on path, e.g.
* xhive:/plays#//TITLE
*/
private class XhiveURIResolver implements URIResolver {
private static final String XHIVE_PREFIX = "xhive:";
private static final String SEPARATOR = "#";
private XhiveSessionIf session;
public XhiveURIResolver(XhiveSessionIf session) {
this.session = session;
}
public Source resolve(String href, String base) throws TransformerException {
// Do we need to do anything?
if (((base == null) || (!base.startsWith(XHIVE_PREFIX))) &&
(!href.startsWith(XHIVE_PREFIX))) {
return null;
} else {
// Process href
// Up to us to come up with a result
if (!href.startsWith(XHIVE_PREFIX)) {
// Create href with base
href = base + href;
}
// Strip xhive: from href
href = href.substring(XHIVE_PREFIX.length());
if (!href.startsWith("/")) {
href = "/" + href;
}
// Separate in path and query
String path = null;
String query = null;
if (href.indexOf(SEPARATOR) != -1) {
path = href.substring(0, href.indexOf(SEPARATOR));
query = href.substring(href.indexOf(SEPARATOR) + 1);
} else {
path = href;
}
// Get query context
XhiveLibraryChildIf contextNode = session.getDatabase().getRoot().getByPath(path);
if (contextNode == null) {
// Nothing found, error or null?
throw new TransformerException("XhiveXalanTransfomer: Could not resolve " + href);
//return null;
} else {
if (query == null) {
if (contextNode instanceof XhiveDocumentIf) {
return new DOMSource(contextNode);
} else if (contextNode instanceof XhiveBlobNodeIf) {
return new StreamSource(((XhiveBlobNodeIf) contextNode).getContents());
} else {
throw new TransformerException("XhiveXalanTransfomer: " + href + " is not a document");
}
} else {
return getExecuteQuerySource(contextNode, query, href);
}
}
}
}
private Source getExecuteQuerySource(XhiveLibraryChildIf contextNode, String query, String href) throws TransformerException {
if (query.startsWith("xpointer(") && query.endsWith(")")) {
query = query.substring("xpointer(".length(), query.length() - 1);
}
Iterator queryResult = null;
try {
queryResult = contextNode.executeXQuery(query);
} catch (XhiveException e) {
throw new TransformerException("XhiveXalanTransformer: Problem with query " + href + ": " + e.getMessage(), e);
}
// We will only use the first result here (otherwise we would have to include a new top-element)
if (queryResult.hasNext()) {
XhiveXQueryValueIf queryValue = (XhiveXQueryValueIf) queryResult.next();
// Is it a node?
try {
return new DOMSource(queryValue.asNode());
} catch (XhiveException e) {
// must be XQUERY_ERROR_VALUE, so interpret it as a string
return new StreamSource(new StringReader(queryValue.asString()));
}
} else {
throw new TransformerException("XhiveXalanTransformer: Query " + href + ": " + " has no results");
}
}
}
For improved Xalan XSLT performance, it may be wise to create Templates
objects using the newTemplates call on TransformerFactory.
What follows is an example of this, see the Xalan documentation for details.
TransformerFactory tFactory = TransformerFactory.newInstance(); tFactory. translet = tFactory.newTemplates(new DOMSource(xslSource)); // Now keep this translet cached somewhere, and for transforming do: Transformer transformer = translet.newTransformer(); transformer.transform( new DOMSource(xmlSource), new StreamResult(writer)) ) ;