001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 /* 019 * $Id: DOM2Helper.java 468655 2006-10-28 07:12:06Z minchau $ 020 */ 021 package org.apache.xml.utils; 022 023 import java.io.IOException; 024 025 import javax.xml.parsers.DocumentBuilder; 026 import javax.xml.parsers.DocumentBuilderFactory; 027 import javax.xml.parsers.ParserConfigurationException; 028 import javax.xml.transform.TransformerException; 029 030 import org.w3c.dom.Attr; 031 import org.w3c.dom.Document; 032 import org.w3c.dom.Element; 033 import org.w3c.dom.Node; 034 035 import org.xml.sax.InputSource; 036 037 /** 038 * @deprecated Since the introduction of the DTM, this class will be removed. 039 * This class provides a DOM level 2 "helper", which provides services currently 040 * not provided be the DOM standard. 041 */ 042 public class DOM2Helper extends DOMHelper 043 { 044 045 /** 046 * Construct an instance. 047 */ 048 public DOM2Helper(){} 049 050 /** 051 * Check node to see if it was created by a DOM implementation 052 * that this helper is intended to support. This is currently 053 * disabled, and assumes all nodes are acceptable rather than checking 054 * that they implement org.apache.xerces.dom.NodeImpl. 055 * 056 * @param node The node to be tested. 057 * 058 * @throws TransformerException if the node is not one which this 059 * DOM2Helper can support. If we return without throwing the exception, 060 * the node is compatable. 061 * @xsl.usage internal 062 */ 063 public void checkNode(Node node) throws TransformerException 064 { 065 066 // if(!(node instanceof org.apache.xerces.dom.NodeImpl)) 067 // throw new TransformerException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_XERCES_CANNOT_HANDLE_NODES, new Object[]{((Object)node).getClass()})); //"DOM2Helper can not handle nodes of type" 068 //+((Object)node).getClass()); 069 } 070 071 /** 072 * Returns true if the DOM implementation handled by this helper 073 * supports the SAX ContentHandler interface. 074 * 075 * @return true (since Xerces does). 076 */ 077 public boolean supportsSAX() 078 { 079 return true; 080 } 081 082 /** Field m_doc: Document Node for the document this helper is currently 083 * accessing or building 084 * @see #setDocument 085 * @see #getDocument 086 * */ 087 private Document m_doc; 088 089 /** 090 * Specify which document this helper is currently operating on. 091 * 092 * @param doc The DOM Document node for this document. 093 * @see #getDocument 094 */ 095 public void setDocument(Document doc) 096 { 097 m_doc = doc; 098 } 099 100 /** 101 * Query which document this helper is currently operating on. 102 * 103 * @return The DOM Document node for this document. 104 * @see #setDocument 105 */ 106 public Document getDocument() 107 { 108 return m_doc; 109 } 110 111 /** 112 * Parse an XML document. 113 * 114 * <p>Right now the Xerces DOMParser class is used. This needs 115 * fixing, either via jaxp, or via some other, standard method.</p> 116 * 117 * <p>The application can use this method to instruct the SAX parser 118 * to begin parsing an XML document from any valid input 119 * source (a character stream, a byte stream, or a URI).</p> 120 * 121 * <p>Applications may not invoke this method while a parse is in 122 * progress (they should create a new Parser instead for each 123 * additional XML document). Once a parse is complete, an 124 * application may reuse the same Parser object, possibly with a 125 * different input source.</p> 126 * 127 * @param source The input source for the top-level of the 128 * XML document. 129 * 130 * @throws TransformerException if any checked exception is thrown. 131 * @xsl.usage internal 132 */ 133 public void parse(InputSource source) throws TransformerException 134 { 135 136 try 137 { 138 139 // I guess I should use JAXP factory here... when it's legal. 140 // org.apache.xerces.parsers.DOMParser parser 141 // = new org.apache.xerces.parsers.DOMParser(); 142 DocumentBuilderFactory builderFactory = 143 DocumentBuilderFactory.newInstance(); 144 145 builderFactory.setNamespaceAware(true); 146 builderFactory.setValidating(true); 147 148 DocumentBuilder parser = builderFactory.newDocumentBuilder(); 149 150 /* 151 // domParser.setFeature("http://apache.org/xml/features/dom/create-entity-ref-nodes", getShouldExpandEntityRefs()? false : true); 152 if(m_useDOM2getNamespaceURI) 153 { 154 parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", true); 155 parser.setFeature("http://xml.org/sax/features/namespaces", true); 156 } 157 else 158 { 159 parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false); 160 } 161 162 parser.setFeature("http://apache.org/xml/features/allow-java-encodings", true); 163 */ 164 165 parser.setErrorHandler( 166 new org.apache.xml.utils.DefaultErrorHandler()); 167 168 // if(null != m_entityResolver) 169 // { 170 // System.out.println("Setting the entity resolver."); 171 // parser.setEntityResolver(m_entityResolver); 172 // } 173 setDocument(parser.parse(source)); 174 } 175 catch (org.xml.sax.SAXException se) 176 { 177 throw new TransformerException(se); 178 } 179 catch (ParserConfigurationException pce) 180 { 181 throw new TransformerException(pce); 182 } 183 catch (IOException ioe) 184 { 185 throw new TransformerException(ioe); 186 } 187 188 // setDocument(((org.apache.xerces.parsers.DOMParser)parser).getDocument()); 189 } 190 191 /** 192 * Given an XML ID, return the element. This requires assistance from the 193 * DOM and parser, and is meaningful only in the context of a DTD 194 * or schema which declares attributes as being of type ID. This 195 * information may or may not be available in all parsers, may or 196 * may not be available for specific documents, and may or may not 197 * be available when validation is not turned on. 198 * 199 * @param id The ID to search for, as a String. 200 * @param doc The document to search within, as a DOM Document node. 201 * @return DOM Element node with an attribute of type ID whose value 202 * uniquely matches the requested id string, or null if there isn't 203 * such an element or if the DOM can't answer the question for other 204 * reasons. 205 */ 206 public Element getElementByID(String id, Document doc) 207 { 208 return doc.getElementById(id); 209 } 210 211 /** 212 * Figure out whether node2 should be considered as being later 213 * in the document than node1, in Document Order as defined 214 * by the XPath model. This may not agree with the ordering defined 215 * by other XML applications. 216 * <p> 217 * There are some cases where ordering isn't defined, and neither are 218 * the results of this function -- though we'll generally return true. 219 * <p> 220 * TODO: Make sure this does the right thing with attribute nodes!!! 221 * 222 * @param node1 DOM Node to perform position comparison on. 223 * @param node2 DOM Node to perform position comparison on . 224 * 225 * @return false if node2 comes before node1, otherwise return true. 226 * You can think of this as 227 * <code>(node1.documentOrderPosition <= node2.documentOrderPosition)</code>. 228 */ 229 public static boolean isNodeAfter(Node node1, Node node2) 230 { 231 232 // Assume first that the nodes are DTM nodes, since discovering node 233 // order is massivly faster for the DTM. 234 if(node1 instanceof DOMOrder && node2 instanceof DOMOrder) 235 { 236 int index1 = ((DOMOrder) node1).getUid(); 237 int index2 = ((DOMOrder) node2).getUid(); 238 239 return index1 <= index2; 240 } 241 else 242 { 243 244 // isNodeAfter will return true if node is after countedNode 245 // in document order. The base isNodeAfter is sloooow (relatively). 246 return DOMHelper.isNodeAfter(node1, node2); 247 } 248 } 249 250 /** 251 * Get the XPath-model parent of a node. This version takes advantage 252 * of the DOM Level 2 Attr.ownerElement() method; the base version we 253 * would otherwise inherit is prepared to fall back on exhaustively 254 * walking the document to find an Attr's parent. 255 * 256 * @param node Node to be examined 257 * 258 * @return the DOM parent of the input node, if there is one, or the 259 * ownerElement if the input node is an Attr, or null if the node is 260 * a Document, a DocumentFragment, or an orphan. 261 */ 262 public static Node getParentOfNode(Node node) 263 { 264 Node parent=node.getParentNode(); 265 if(parent==null && (Node.ATTRIBUTE_NODE == node.getNodeType()) ) 266 parent=((Attr) node).getOwnerElement(); 267 return parent; 268 } 269 270 /** 271 * Returns the local name of the given node, as defined by the 272 * XML Namespaces specification. This is prepared to handle documents 273 * built using DOM Level 1 methods by falling back upon explicitly 274 * parsing the node name. 275 * 276 * @param n Node to be examined 277 * 278 * @return String containing the local name, or null if the node 279 * was not assigned a Namespace. 280 */ 281 public String getLocalNameOfNode(Node n) 282 { 283 284 String name = n.getLocalName(); 285 286 return (null == name) ? super.getLocalNameOfNode(n) : name; 287 } 288 289 /** 290 * Returns the Namespace Name (Namespace URI) for the given node. 291 * In a Level 2 DOM, you can ask the node itself. Note, however, that 292 * doing so conflicts with our decision in getLocalNameOfNode not 293 * to trust the that the DOM was indeed created using the Level 2 294 * methods. If Level 1 methods were used, these two functions will 295 * disagree with each other. 296 * <p> 297 * TODO: Reconcile with getLocalNameOfNode. 298 * 299 * @param n Node to be examined 300 * 301 * @return String containing the Namespace URI bound to this DOM node 302 * at the time the Node was created. 303 */ 304 public String getNamespaceOfNode(Node n) 305 { 306 return n.getNamespaceURI(); 307 } 308 309 /** Field m_useDOM2getNamespaceURI is a compile-time flag which 310 * gates some of the parser options used to build a DOM -- but 311 * that code is commented out at this time and nobody else 312 * references it, so I've commented this out as well. */ 313 //private boolean m_useDOM2getNamespaceURI = false; 314 }