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