1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 1999 The Apache Software Foundation. All rights
  6. * reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Xalan" and "Apache Software Foundation" must
  28. * not be used to endorse or promote products derived from this
  29. * software without prior written permission. For written
  30. * permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * nor may "Apache" appear in their name, without prior written
  34. * permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation and was
  52. * originally based on software copyright (c) 1999, Lotus
  53. * Development Corporation., http://www.lotus.com. For more
  54. * information on the Apache Software Foundation, please see
  55. * <http://www.apache.org/>.
  56. */
  57. package org.apache.xalan.lib;
  58. // Imported classes for Extension elements
  59. import org.apache.xalan.extensions.XSLProcessorContext;
  60. import org.apache.xalan.templates.ElemExtensionCall;
  61. import org.apache.xalan.templates.ElemLiteralResult;
  62. import org.apache.xalan.templates.AVT;
  63. import org.apache.xalan.transformer.TransformerImpl;
  64. // Imported JAXP/TrAX classes
  65. import javax.xml.transform.TransformerFactory;
  66. import javax.xml.transform.Transformer;
  67. import javax.xml.transform.Templates;
  68. import javax.xml.transform.stream.StreamSource;
  69. import javax.xml.transform.TransformerException;
  70. import javax.xml.transform.TransformerConfigurationException;
  71. import javax.xml.transform.sax.SAXTransformerFactory;
  72. import javax.xml.transform.sax.TransformerHandler;
  73. import javax.xml.transform.sax.SAXResult;
  74. // Imported JAXP parsing classes
  75. import javax.xml.parsers.DocumentBuilder;
  76. import javax.xml.parsers.DocumentBuilderFactory;
  77. import javax.xml.parsers.ParserConfigurationException;
  78. // Imported SAX classes
  79. import org.xml.sax.InputSource;
  80. import org.xml.sax.SAXException;
  81. import org.xml.sax.SAXNotRecognizedException;
  82. import org.xml.sax.Parser;
  83. import org.xml.sax.helpers.ParserAdapter;
  84. import org.xml.sax.helpers.XMLReaderFactory;
  85. import org.xml.sax.XMLReader;
  86. import org.xml.sax.ContentHandler;
  87. import org.xml.sax.ext.LexicalHandler;
  88. // Imported DOM classes
  89. import org.w3c.dom.Node;
  90. import org.w3c.dom.Document;
  91. import org.w3c.dom.Element;
  92. import org.w3c.dom.NodeList;
  93. // Imported Serializer classes
  94. import org.apache.xalan.serialize.Serializer;
  95. import org.apache.xalan.serialize.SerializerFactory;
  96. import org.apache.xalan.templates.OutputProperties;
  97. // Other org.apache imports
  98. import org.apache.xpath.XPathContext;
  99. import org.apache.xml.utils.SystemIDResolver;
  100. // Imported java.io and java.util classes
  101. import java.io.FileOutputStream;
  102. import java.io.IOException;
  103. import java.io.FileNotFoundException;
  104. import java.util.Vector;
  105. import java.util.Properties;
  106. /**
  107. * PipeDocument is a Xalan extension element to set stylesheet params and pipes an XML
  108. * document through a series of 1 or more stylesheets.
  109. * PipeDocument is invoked from a stylesheet as the {@link #pipeDocument pipeDocument extension element}.
  110. *
  111. * It is accessed by specifying a namespace URI as follows:
  112. * <pre>
  113. * xmlns:pipe="http://xml.apache.org/xalan/PipeDocument"
  114. * </pre>
  115. *
  116. * @author Donald Leslie
  117. */
  118. public class PipeDocument
  119. {
  120. /**
  121. * Extension element for piping an XML document through a series of 1 or more transformations.
  122. *
  123. * <pre>Common usage pattern: A stylesheet transforms a listing of documents to be
  124. * transformed into a TOC. For each document in the listing calls the pipeDocument
  125. * extension element to pipe that document through a series of 1 or more stylesheets
  126. * to the desired output document.
  127. *
  128. * Syntax:
  129. * <xsl:stylesheet version="1.0"
  130. * xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  131. * xmlns:pipe="http://xml.apache.org/xalan/PipeDocument"
  132. * extension-element-prefixes="pipe">
  133. * ...
  134. * <pipe:pipeDocument source="source.xml" target="target.xml">
  135. * <stylesheet href="ss1.xsl">
  136. * <param name="param1" value="value1"/>
  137. * </stylesheet>
  138. * <stylesheet href="ss2.xsl">
  139. * <param name="param1" value="value1"/>
  140. * <param name="param2" value="value2"/>
  141. * </stylesheet>
  142. * <stylesheet href="ss1.xsl"/>
  143. * </pipe:pipeDocument>
  144. *
  145. * Notes:</pre>
  146. * <ul>
  147. * <li>The base URI for the source attribute is the XML "listing" document.<li/>
  148. * <li>The target attribute is taken as is (base is the current user directory).<li/>
  149. * <li>The stylsheet containg the extension element is the base URI for the
  150. * stylesheet hrefs.<li/>
  151. * </ul>
  152. */
  153. public void pipeDocument(XSLProcessorContext context, ElemExtensionCall elem)
  154. throws TransformerException, TransformerConfigurationException,
  155. SAXException, IOException, FileNotFoundException
  156. {
  157. try
  158. {
  159. SAXTransformerFactory saxTFactory = (SAXTransformerFactory) TransformerFactory.newInstance();
  160. // XML doc to transform.
  161. String source = elem.getAttribute("source",
  162. context.getContextNode(),
  163. context.getTransformer());
  164. TransformerImpl transImpl = context.getTransformer();
  165. //Base URI for input doc, so base for relative URI to XML doc to transform.
  166. String baseURLOfSource = transImpl.getBaseURLOfSource();
  167. // Absolute URI for XML doc to transform.
  168. String absSourceURL = SystemIDResolver.getAbsoluteURI(source, baseURLOfSource);
  169. // Transformation target
  170. String target = elem.getAttribute("target",
  171. context.getContextNode(),
  172. context.getTransformer());
  173. XPathContext xctxt = context.getTransformer().getXPathContext();
  174. int xt = xctxt.getDTMHandleFromNode(context.getContextNode());
  175. // Get System Id for stylesheet; to be used to resolve URIs to other stylesheets.
  176. String sysId = elem.getSystemId();
  177. NodeList ssNodes = null;
  178. NodeList paramNodes = null;
  179. Node ssNode = null;
  180. Node paramNode = null;
  181. if (elem.hasChildNodes())
  182. {
  183. ssNodes = elem.getChildNodes();
  184. // Vector to contain TransformerHandler for each stylesheet.
  185. Vector vTHandler = new Vector(ssNodes.getLength());
  186. // The child nodes of an extension element node are instances of
  187. // ElemLiteralResult, which requires does not fully support the standard
  188. // Node interface. Accordingly, some special handling is required (see below)
  189. // to get attribute values.
  190. for (int i = 0; i < ssNodes.getLength(); i++)
  191. {
  192. ssNode = ssNodes.item(i);
  193. if (ssNode.getNodeType() == ssNode.ELEMENT_NODE
  194. && ((Element)ssNode).getTagName().equals("stylesheet")
  195. && ssNode instanceof ElemLiteralResult)
  196. {
  197. AVT avt = ((ElemLiteralResult)ssNode).getLiteralResultAttribute("href");
  198. String href = avt.evaluate(xctxt,xt, elem);
  199. String absURI = SystemIDResolver.getAbsoluteURI(href, sysId);
  200. Templates tmpl = saxTFactory.newTemplates(new StreamSource(absURI));
  201. TransformerHandler tHandler = saxTFactory.newTransformerHandler(tmpl);
  202. Transformer trans = tHandler.getTransformer();
  203. // AddTransformerHandler to vector
  204. vTHandler.addElement(tHandler);
  205. paramNodes = ssNode.getChildNodes();
  206. for (int j = 0; j < paramNodes.getLength(); j++)
  207. {
  208. paramNode = paramNodes.item(j);
  209. if (paramNode.getNodeType() == paramNode.ELEMENT_NODE
  210. && ((Element)paramNode).getTagName().equals("param")
  211. && paramNode instanceof ElemLiteralResult)
  212. {
  213. avt = ((ElemLiteralResult)paramNode).getLiteralResultAttribute("name");
  214. String pName = avt.evaluate(xctxt,xt, elem);
  215. avt = ((ElemLiteralResult)paramNode).getLiteralResultAttribute("value");
  216. String pValue = avt.evaluate(xctxt,xt, elem);
  217. trans.setParameter(pName, pValue);
  218. }
  219. }
  220. }
  221. }
  222. usePipe(vTHandler, absSourceURL, target);
  223. }
  224. }
  225. catch (Exception e)
  226. {
  227. e.printStackTrace();
  228. }
  229. }
  230. /**
  231. * Uses a Vector of TransformerHandlers to pipe XML input document through
  232. * a series of 1 or more transformations. Called by {@link #pipeDocument} and {@link #main}.
  233. *
  234. * @param vTHandler Vector of Transformation Handlers (1 per stylesheet).
  235. * @param source absolute URI to XML input
  236. * @param target absolute path to transformation output.
  237. */
  238. public void usePipe(Vector vTHandler, String source, String target)
  239. throws TransformerException, TransformerConfigurationException,
  240. FileNotFoundException, IOException, SAXException, SAXNotRecognizedException
  241. {
  242. XMLReader reader = XMLReaderFactory.createXMLReader();
  243. TransformerHandler tHFirst = (TransformerHandler)vTHandler.firstElement();
  244. reader.setContentHandler(tHFirst);
  245. reader.setProperty("http://xml.org/sax/properties/lexical-handler", tHFirst);
  246. for (int i = 1; i < vTHandler.size(); i++)
  247. {
  248. TransformerHandler tHFrom = (TransformerHandler)vTHandler.elementAt(i-1);
  249. TransformerHandler tHTo = (TransformerHandler)vTHandler.elementAt(i);
  250. tHFrom.setResult(new SAXResult(tHTo));
  251. }
  252. TransformerHandler tHLast = (TransformerHandler)vTHandler.lastElement();
  253. Transformer trans = tHLast.getTransformer();
  254. Properties outputProps = trans.getOutputProperties();
  255. Serializer serializer = SerializerFactory.getSerializer(outputProps);
  256. serializer.setOutputStream(new FileOutputStream(target));
  257. tHLast.setResult(new SAXResult(serializer.asContentHandler()));
  258. reader.parse(source);
  259. }
  260. }