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.xpath;
  58. import java.io.IOException;
  59. import java.util.StringTokenizer;
  60. import org.apache.xpath.res.XPATHErrorResources;
  61. import org.apache.xalan.res.XSLMessages;
  62. import org.apache.xpath.DOMHelper;
  63. import org.w3c.dom.Node;
  64. import org.w3c.dom.Document;
  65. import org.w3c.dom.Element;
  66. import org.w3c.dom.Text;
  67. import org.w3c.dom.Attr;
  68. import org.xml.sax.InputSource;
  69. import org.xml.sax.Parser;
  70. import javax.xml.parsers.*;
  71. import javax.xml.transform.TransformerException;
  72. /**
  73. * @deprecated Since the introduction of the DTM, this class will be removed.
  74. * This class provides a DOM level 2 "helper", which provides services currently
  75. * not provided be the DOM standard.
  76. */
  77. public class DOM2Helper extends DOMHelper
  78. {
  79. /**
  80. * Construct an instance.
  81. */
  82. public DOM2Helper(){}
  83. /**
  84. * <meta name="usage" content="internal"/>
  85. * Check node to see if it was created by a DOM implementation
  86. * that this helper is intended to support. This is currently
  87. * disabled, and assumes all nodes are acceptable rather than checking
  88. * that they implement org.apache.xerces.dom.NodeImpl.
  89. *
  90. * @param node The node to be tested.
  91. *
  92. * @throws TransformerException if the node is not one which this
  93. * DOM2Helper can support. If we return without throwing the exception,
  94. * the node is compatable.
  95. */
  96. public void checkNode(Node node) throws TransformerException
  97. {
  98. // if(!(node instanceof org.apache.xerces.dom.NodeImpl))
  99. // throw new TransformerException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_XERCES_CANNOT_HANDLE_NODES, new Object[]{((Object)node).getClass()})); //"DOM2Helper can not handle nodes of type"
  100. //+((Object)node).getClass());
  101. }
  102. /**
  103. * Returns true if the DOM implementation handled by this helper
  104. * supports the SAX ContentHandler interface.
  105. *
  106. * @return true (since Xerces does).
  107. */
  108. public boolean supportsSAX()
  109. {
  110. return true;
  111. }
  112. /** Field m_doc: Document Node for the document this helper is currently
  113. * accessing or building
  114. * @see #setDocument
  115. * @see #getDocument
  116. * */
  117. private Document m_doc;
  118. /**
  119. * Specify which document this helper is currently operating on.
  120. *
  121. * @param doc The DOM Document node for this document.
  122. * @see #getDocument
  123. */
  124. public void setDocument(Document doc)
  125. {
  126. m_doc = doc;
  127. }
  128. /**
  129. * Query which document this helper is currently operating on.
  130. *
  131. * @return The DOM Document node for this document.
  132. * @see #setDocument
  133. */
  134. public Document getDocument()
  135. {
  136. return m_doc;
  137. }
  138. /**
  139. * <meta name="usage" content="internal"/>
  140. * Parse an XML document.
  141. *
  142. * <p>Right now the Xerces DOMParser class is used. This needs
  143. * fixing, either via jaxp, or via some other, standard method.</p>
  144. *
  145. * <p>The application can use this method to instruct the SAX parser
  146. * to begin parsing an XML document from any valid input
  147. * source (a character stream, a byte stream, or a URI).</p>
  148. *
  149. * <p>Applications may not invoke this method while a parse is in
  150. * progress (they should create a new Parser instead for each
  151. * additional XML document). Once a parse is complete, an
  152. * application may reuse the same Parser object, possibly with a
  153. * different input source.</p>
  154. *
  155. * @param source The input source for the top-level of the
  156. * XML document.
  157. *
  158. * @throws TransformerException if any checked exception is thrown.
  159. */
  160. public void parse(InputSource source) throws TransformerException
  161. {
  162. try
  163. {
  164. // I guess I should use JAXP factory here... when it's legal.
  165. // org.apache.xerces.parsers.DOMParser parser
  166. // = new org.apache.xerces.parsers.DOMParser();
  167. DocumentBuilderFactory builderFactory =
  168. DocumentBuilderFactory.newInstance();
  169. builderFactory.setNamespaceAware(true);
  170. builderFactory.setValidating(true);
  171. DocumentBuilder parser = builderFactory.newDocumentBuilder();
  172. /*
  173. // domParser.setFeature("http://apache.org/xml/features/dom/create-entity-ref-nodes", getShouldExpandEntityRefs()? false : true);
  174. if(m_useDOM2getNamespaceURI)
  175. {
  176. parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", true);
  177. parser.setFeature("http://xml.org/sax/features/namespaces", true);
  178. }
  179. else
  180. {
  181. parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
  182. }
  183. parser.setFeature("http://apache.org/xml/features/allow-java-encodings", true);
  184. */
  185. parser.setErrorHandler(
  186. new org.apache.xml.utils.DefaultErrorHandler());
  187. // if(null != m_entityResolver)
  188. // {
  189. // System.out.println("Setting the entity resolver.");
  190. // parser.setEntityResolver(m_entityResolver);
  191. // }
  192. setDocument(parser.parse(source));
  193. }
  194. catch (org.xml.sax.SAXException se)
  195. {
  196. throw new TransformerException(se);
  197. }
  198. catch (ParserConfigurationException pce)
  199. {
  200. throw new TransformerException(pce);
  201. }
  202. catch (IOException ioe)
  203. {
  204. throw new TransformerException(ioe);
  205. }
  206. // setDocument(((org.apache.xerces.parsers.DOMParser)parser).getDocument());
  207. }
  208. /**
  209. * Given an XML ID, return the element. This requires assistance from the
  210. * DOM and parser, and is meaningful only in the context of a DTD
  211. * or schema which declares attributes as being of type ID. This
  212. * information may or may not be available in all parsers, may or
  213. * may not be available for specific documents, and may or may not
  214. * be available when validation is not turned on.
  215. *
  216. * @param id The ID to search for, as a String.
  217. * @param doc The document to search within, as a DOM Document node.
  218. * @return DOM Element node with an attribute of type ID whose value
  219. * uniquely matches the requested id string, or null if there isn't
  220. * such an element or if the DOM can't answer the question for other
  221. * reasons.
  222. */
  223. public Element getElementByID(String id, Document doc)
  224. {
  225. return doc.getElementById(id);
  226. }
  227. /**
  228. * Figure out whether node2 should be considered as being later
  229. * in the document than node1, in Document Order as defined
  230. * by the XPath model. This may not agree with the ordering defined
  231. * by other XML applications.
  232. * <p>
  233. * There are some cases where ordering isn't defined, and neither are
  234. * the results of this function -- though we'll generally return true.
  235. * <p>
  236. * TODO: Make sure this does the right thing with attribute nodes!!!
  237. *
  238. * @param node1 DOM Node to perform position comparison on.
  239. * @param node2 DOM Node to perform position comparison on .
  240. *
  241. * @return false if node2 comes before node1, otherwise return true.
  242. * You can think of this as
  243. * <code>(node1.documentOrderPosition <= node2.documentOrderPosition)</code>.
  244. */
  245. public static boolean isNodeAfter(Node node1, Node node2)
  246. {
  247. // Assume first that the nodes are DTM nodes, since discovering node
  248. // order is massivly faster for the DTM.
  249. if(node1 instanceof DOMOrder && node2 instanceof DOMOrder)
  250. {
  251. int index1 = ((DOMOrder) node1).getUid();
  252. int index2 = ((DOMOrder) node2).getUid();
  253. return index1 <= index2;
  254. }
  255. else
  256. {
  257. // isNodeAfter will return true if node is after countedNode
  258. // in document order. The base isNodeAfter is sloooow (relatively).
  259. return DOMHelper.isNodeAfter(node1, node2);
  260. }
  261. }
  262. /**
  263. * Get the XPath-model parent of a node. This version takes advantage
  264. * of the DOM Level 2 Attr.ownerElement() method; the base version we
  265. * would otherwise inherit is prepared to fall back on exhaustively
  266. * walking the document to find an Attr's parent.
  267. *
  268. * @param node Node to be examined
  269. *
  270. * @return the DOM parent of the input node, if there is one, or the
  271. * ownerElement if the input node is an Attr, or null if the node is
  272. * a Document, a DocumentFragment, or an orphan.
  273. */
  274. public static Node getParentOfNode(Node node)
  275. {
  276. Node parent=node.getParentNode();
  277. if(parent==null && (Node.ATTRIBUTE_NODE == node.getNodeType()) )
  278. parent=((Attr) node).getOwnerElement();
  279. return parent;
  280. }
  281. /**
  282. * Returns the local name of the given node, as defined by the
  283. * XML Namespaces specification. This is prepared to handle documents
  284. * built using DOM Level 1 methods by falling back upon explicitly
  285. * parsing the node name.
  286. *
  287. * @param n Node to be examined
  288. *
  289. * @return String containing the local name, or null if the node
  290. * was not assigned a Namespace.
  291. */
  292. public String getLocalNameOfNode(Node n)
  293. {
  294. String name = n.getLocalName();
  295. return (null == name) ? super.getLocalNameOfNode(n) : name;
  296. }
  297. /**
  298. * Returns the Namespace Name (Namespace URI) for the given node.
  299. * In a Level 2 DOM, you can ask the node itself. Note, however, that
  300. * doing so conflicts with our decision in getLocalNameOfNode not
  301. * to trust the that the DOM was indeed created using the Level 2
  302. * methods. If Level 1 methods were used, these two functions will
  303. * disagree with each other.
  304. * <p>
  305. * TODO: Reconcile with getLocalNameOfNode.
  306. *
  307. * @param n Node to be examined
  308. *
  309. * @return String containing the Namespace URI bound to this DOM node
  310. * at the time the Node was created.
  311. */
  312. public String getNamespaceOfNode(Node n)
  313. {
  314. return n.getNamespaceURI();
  315. }
  316. /** Field m_useDOM2getNamespaceURI is a compile-time flag which
  317. * gates some of the parser options used to build a DOM -- but
  318. * that code is commented out at this time and nobody else
  319. * references it, so I've commented this out as well. */
  320. //private boolean m_useDOM2getNamespaceURI = false;
  321. }