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.extensions;
  58. import org.w3c.dom.Node;
  59. import org.w3c.dom.DocumentFragment;
  60. import org.w3c.dom.traversal.NodeIterator;
  61. import org.apache.xml.dtm.*;
  62. import org.apache.xalan.transformer.TransformerImpl;
  63. import org.apache.xalan.transformer.ResultTreeHandler;
  64. import org.apache.xalan.transformer.ClonerToResultTree;
  65. import org.apache.xalan.templates.Stylesheet;
  66. import org.apache.xml.utils.QName;
  67. import javax.xml.transform.TransformerException;
  68. import org.apache.xpath.objects.XObject;
  69. import org.apache.xpath.objects.XString;
  70. import org.apache.xpath.objects.XBoolean;
  71. import org.apache.xpath.objects.XNumber;
  72. import org.apache.xpath.objects.XRTreeFrag;
  73. import org.apache.xpath.objects.XNodeSet;
  74. import org.apache.xpath.XPathContext;
  75. import org.apache.xpath.axes.DescendantIterator;
  76. import org.apache.xpath.axes.OneStepIterator;
  77. import org.apache.xml.dtm.DTM;
  78. // import org.apache.xalan.xslt.*;
  79. /**
  80. * <meta name="usage" content="general"/>
  81. * Provides transformer context to be passed to an extension element.
  82. *
  83. * @author Sanjiva Weerawarana (sanjiva@watson.ibm.com)
  84. */
  85. public class XSLProcessorContext
  86. {
  87. /**
  88. * Create a processor context to be passed to an extension.
  89. * (Notice it is a package-only constructor).
  90. *
  91. * @param transformer non-null transformer instance
  92. * @param stylesheetTree The owning stylesheet
  93. * @param sourceTree The source document
  94. * @param sourceNode The current source node
  95. * @param mode the current mode being executed.
  96. */
  97. public XSLProcessorContext(TransformerImpl transformer,
  98. Stylesheet stylesheetTree)
  99. {
  100. this.transformer = transformer;
  101. this.stylesheetTree = stylesheetTree;
  102. // %TBD%
  103. org.apache.xpath.XPathContext xctxt = transformer.getXPathContext();
  104. this.mode = transformer.getMode();
  105. this.sourceNode = xctxt.getCurrentNode();
  106. this.sourceTree = xctxt.getDTM(this.sourceNode);
  107. }
  108. /** An instance of a transformer */
  109. private TransformerImpl transformer;
  110. /**
  111. * Get the transformer.
  112. *
  113. * @return the transformer instance for this context
  114. */
  115. public TransformerImpl getTransformer()
  116. {
  117. return transformer;
  118. }
  119. /** The owning stylesheet for this context */
  120. private Stylesheet stylesheetTree;
  121. /**
  122. * Get the Stylesheet being executed.
  123. *
  124. * @return the Stylesheet being executed.
  125. */
  126. public Stylesheet getStylesheet()
  127. {
  128. return stylesheetTree;
  129. }
  130. /** The root of the source tree being executed. */
  131. private org.apache.xml.dtm.DTM sourceTree;
  132. /**
  133. * Get the root of the source tree being executed.
  134. *
  135. * @return the root of the source tree being executed.
  136. */
  137. public org.w3c.dom.Node getSourceTree()
  138. {
  139. return sourceTree.getNode(sourceTree.getDocumentRoot(sourceNode));
  140. }
  141. /** the current context node. */
  142. private int sourceNode;
  143. /**
  144. * Get the current context node.
  145. *
  146. * @return the current context node.
  147. */
  148. public org.w3c.dom.Node getContextNode()
  149. {
  150. return sourceTree.getNode(sourceNode);
  151. }
  152. /** the current mode being executed. */
  153. private QName mode;
  154. /**
  155. * Get the current mode being executed.
  156. *
  157. * @return the current mode being executed.
  158. */
  159. public QName getMode()
  160. {
  161. return mode;
  162. }
  163. /**
  164. * Output an object to the result tree by doing the right conversions.
  165. * This is public for access by extensions.
  166. *
  167. *
  168. * @param stylesheetTree The owning stylesheet
  169. * @param obj the Java object to output. If its of an X<something> type
  170. * then that conversion is done first and then sent out.
  171. *
  172. * @throws TransformerException
  173. * @throws java.io.FileNotFoundException
  174. * @throws java.io.IOException
  175. * @throws java.net.MalformedURLException
  176. */
  177. public void outputToResultTree(Stylesheet stylesheetTree, Object obj)
  178. throws TransformerException, java.net.MalformedURLException,
  179. java.io.FileNotFoundException, java.io.IOException
  180. {
  181. try
  182. {
  183. ResultTreeHandler rtreeHandler = transformer.getResultTreeHandler();
  184. XPathContext xctxt = transformer.getXPathContext();
  185. XObject value;
  186. // Make the return object into an XObject because it
  187. // will be easier below. One of the reasons to do this
  188. // is to keep all the conversion functionality in the
  189. // XObject classes.
  190. if (obj instanceof XObject)
  191. {
  192. value = (XObject) obj;
  193. }
  194. else if (obj instanceof String)
  195. {
  196. value = new XString((String) obj);
  197. }
  198. else if (obj instanceof Boolean)
  199. {
  200. value = new XBoolean(((Boolean) obj).booleanValue());
  201. }
  202. else if (obj instanceof Double)
  203. {
  204. value = new XNumber(((Double) obj).doubleValue());
  205. }
  206. else if (obj instanceof DocumentFragment)
  207. {
  208. int handle = xctxt.getDTMHandleFromNode((DocumentFragment)obj);
  209. value = new XRTreeFrag(handle, xctxt);
  210. }
  211. else if (obj instanceof DTM)
  212. {
  213. DTM dtm = (DTM)obj;
  214. DTMIterator iterator = new DescendantIterator();
  215. // %%ISSUE%% getDocument may not be valid for DTMs shared by multiple
  216. // document trees, eg RTFs. But in that case, we shouldn't be trying
  217. // to iterate over the whole DTM; we should be iterating over
  218. // dtm.getDocumentRoot(rootNodeHandle), and folks should have told us
  219. // this by passing a more appropriate type.
  220. iterator.setRoot(dtm.getDocument(), xctxt);
  221. value = new XNodeSet(iterator);
  222. }
  223. else if (obj instanceof DTMAxisIterator)
  224. {
  225. DTMAxisIterator iter = (DTMAxisIterator)obj;
  226. DTMIterator iterator = new OneStepIterator(iter, -1);
  227. value = new XNodeSet(iterator);
  228. }
  229. else if (obj instanceof DTMIterator)
  230. {
  231. value = new XNodeSet((DTMIterator) obj);
  232. }
  233. else if (obj instanceof NodeIterator)
  234. {
  235. value = new XNodeSet(new org.apache.xpath.NodeSetDTM(((NodeIterator)obj), xctxt));
  236. }
  237. else if (obj instanceof org.w3c.dom.Node)
  238. {
  239. value =
  240. new XNodeSet(xctxt.getDTMHandleFromNode((org.w3c.dom.Node) obj),
  241. xctxt.getDTMManager());
  242. }
  243. else
  244. {
  245. value = new XString(obj.toString());
  246. }
  247. int type = value.getType();
  248. String s;
  249. switch (type)
  250. {
  251. case XObject.CLASS_BOOLEAN :
  252. case XObject.CLASS_NUMBER :
  253. case XObject.CLASS_STRING :
  254. s = value.str();
  255. rtreeHandler.characters(s.toCharArray(), 0, s.length());
  256. break;
  257. case XObject.CLASS_NODESET : // System.out.println(value);
  258. DTMIterator nl = value.iter();
  259. int pos;
  260. while (DTM.NULL != (pos = nl.nextNode()))
  261. {
  262. DTM dtm = nl.getDTM(pos);
  263. int top = pos;
  264. while (DTM.NULL != pos)
  265. {
  266. rtreeHandler.flushPending();
  267. ClonerToResultTree.cloneToResultTree(pos, dtm.getNodeType(pos),
  268. dtm, rtreeHandler, true);
  269. int nextNode = dtm.getFirstChild(pos);
  270. while (DTM.NULL == nextNode)
  271. {
  272. if (DTM.ELEMENT_NODE == dtm.getNodeType(pos))
  273. {
  274. rtreeHandler.endElement("", "", dtm.getNodeName(pos));
  275. }
  276. if (top == pos)
  277. break;
  278. nextNode = dtm.getNextSibling(pos);
  279. if (DTM.NULL == nextNode)
  280. {
  281. pos = dtm.getParent(pos);
  282. if (top == pos)
  283. {
  284. if (DTM.ELEMENT_NODE == dtm.getNodeType(pos))
  285. {
  286. rtreeHandler.endElement("", "", dtm.getNodeName(pos));
  287. }
  288. nextNode = DTM.NULL;
  289. break;
  290. }
  291. }
  292. }
  293. pos = nextNode;
  294. }
  295. }
  296. break;
  297. case XObject.CLASS_RTREEFRAG :
  298. rtreeHandler.outputResultTreeFragment(value,
  299. transformer.getXPathContext());
  300. break;
  301. }
  302. }
  303. catch(org.xml.sax.SAXException se)
  304. {
  305. throw new TransformerException(se);
  306. }
  307. }
  308. /**
  309. * I need a "Node transformNode (Node)" method somewhere that the
  310. * user can call to process the transformation of a node but not
  311. * serialize out automatically. ????????????????
  312. *
  313. * Does ElemTemplateElement.executeChildTemplates() cut it? It sends
  314. * results out to the stream directly, so that could be a problem.
  315. */
  316. }