001: /*
002: * $Id: XPathHelper.java,v 1.5 2002/07/18 06:02:22 skavish Exp $
003: *
004: * ===========================================================================
005: *
006: * The JGenerator Software License, Version 1.0
007: *
008: * Copyright (c) 2000 Dmitry Skavish (skavish@usa.net). All rights reserved.
009: *
010: * Redistribution and use in source and binary forms, with or without
011: * modification, are permitted provided that the following conditions are met:
012: *
013: * 1. Redistributions of source code must retain the above copyright
014: * notice, this list of conditions and the following disclaimer.
015: *
016: * 2. Redistributions in binary form must reproduce the above copyright
017: * notice, this list of conditions and the following disclaimer in
018: * the documentation and/or other materials provided with the
019: * distribution.
020: *
021: * 3. The end-user documentation included with the redistribution, if
022: * any, must include the following acknowlegement:
023: * "This product includes software developed by Dmitry Skavish
024: * (skavish@usa.net, http://www.flashgap.com/)."
025: * Alternately, this acknowlegement may appear in the software itself,
026: * if and wherever such third-party acknowlegements normally appear.
027: *
028: * 4. The name "The JGenerator" must not be used to endorse or promote
029: * products derived from this software without prior written permission.
030: * For written permission, please contact skavish@usa.net.
031: *
032: * 5. Products derived from this software may not be called "The JGenerator"
033: * nor may "The JGenerator" appear in their names without prior written
034: * permission of Dmitry Skavish.
035: *
036: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
037: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
038: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
039: * DISCLAIMED. IN NO EVENT SHALL DMITRY SKAVISH OR THE OTHER
040: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
041: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
042: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
043: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
044: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
045: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
046: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
047: * SUCH DAMAGE.
048: *
049: */
050:
051: package org.openlaszlo.iv.flash.xml.apache;
052:
053: import java.io.*;
054: import java.net.*;
055: import java.util.*;
056:
057: import java.io.FileInputStream;
058: import java.io.FileNotFoundException;
059: import java.util.Properties;
060:
061: import org.apache.xerces.parsers.DOMParser;
062: import org.apache.xpath.*;
063: import org.apache.xml.utils.*;
064: import org.apache.xpath.objects.*;
065: import org.w3c.dom.*;
066: import org.w3c.dom.traversal.*;
067: import org.xml.sax.SAXException;
068: import org.xml.sax.InputSource;
069:
070: import javax.xml.parsers.*;
071: import javax.xml.transform.*;
072:
073: import org.openlaszlo.iv.flash.api.*;
074: import org.openlaszlo.iv.flash.url.*;
075:
076: import org.openlaszlo.iv.flash.cache.*;
077:
078: import org.xml.sax.EntityResolver;
079: import org.xml.sax.InputSource;
080:
081: /**
082: * XML Helper class for apache implementation
083: * <P>
084: * Provides various methods for XML stuff
085: *
086: * @author Dmitry Skavish
087: */
088: public class XPathHelper {
089:
090: private static Hashtable xpaths = new Hashtable();
091: private static Hashtable prefix_resolvers = new Hashtable();
092:
093: public synchronized static PrefixResolver getPrefixResolver(
094: Node node) {
095: if (prefix_resolvers.size() > 300)
096: prefix_resolvers.clear();
097:
098: PrefixResolver pr = (PrefixResolver) prefix_resolvers.get(node);
099: if (pr == null) {
100: // Create an object to resolve namespace prefixes.
101: // XPath namespaces are resolved from the input context node's document element
102: // if it is a root node, or else the current context node (for lack of a better
103: // resolution space, given the simplicity of this sample code).
104: pr = new PrefixResolverDefault(
105: (node.getNodeType() == Node.DOCUMENT_NODE) ? ((Document) node)
106: .getDocumentElement()
107: : node);
108: prefix_resolvers.put(node, pr);
109: }
110:
111: return pr;
112: }
113:
114: /**
115: * Compiles specified string into XPath.
116: * <P>
117: * Tries to retrieve compiled XPath expression from cache,
118: * if it's not in the cache then compiles give string into XPath
119: * and caches in the cache.
120: *
121: * @param expr string representing XPath expression
122: * @return compiled XPath expression
123: * @exception TransformerException
124: */
125: public synchronized static XPath getXPath(Node node, String expr)
126: throws TransformerException {
127: if (xpaths.size() > 300)
128: xpaths.clear();
129:
130: XPath xpath = (XPath) xpaths.get(expr);
131: if (xpath == null) {
132: xpath = new XPath(expr, null, getPrefixResolver(node),
133: XPath.SELECT, null);
134: xpaths.put(expr, xpath);
135: }
136: return xpath;
137: }
138:
139: /**
140: * Evaluates specified XPath expression in the specified xml node.
141: *
142: * @param xpathContext
143: * @param node xml node to evaluated on
144: * @param expr xpath expression
145: * @return result of xpath execution
146: * @exception TransformerException
147: */
148: public static XObject evalXPath(XPathContext xpathContext,
149: Node node, String expr) throws TransformerException {
150: return evalXPath(xpathContext, node, getXPath(node, expr));
151: }
152:
153: /**
154: * Evaluates specified XPath expression in the specified xml node.
155: *
156: * @param xpathContext
157: * @param node xml node to evaluated on
158: * @param xpath xpath expression
159: * @return result of xpath execution
160: * @exception TransformerException
161: */
162: public static XObject evalXPath(XPathContext xpathContext,
163: Node node, XPath xpath) throws TransformerException {
164: // Execute the XPath, and have it return the result
165: // return xpath.execute(xpathSupport, contextNode, prefixResolver);
166: int ctxtNode = xpathContext.getDTMHandleFromNode(node);
167:
168: return xpath.execute(xpathContext, ctxtNode,
169: getPrefixResolver(node));
170: }
171:
172: /**
173: * Evaluates XPath to list of nodes.
174: *
175: * @param xpathContext
176: * @param node xml node to evaluated on
177: * @param expr XPath expression
178: * @return result of xpath execution - list of nodes
179: * @exception TransformerException
180: */
181: public static NodeList selectNodeList(XPathContext xpathContext,
182: Node node, String expr) throws TransformerException {
183: return getNodeList(evalXPath(xpathContext, node, expr));
184: }
185:
186: /**
187: * Evaluates XPath to list of nodes.
188: *
189: * @param xpathContext
190: * @param node xml node to evaluated on
191: * @param xpath XPath expression
192: * @return result of xpath execution - list of nodes
193: * @exception TransformerException
194: */
195: public static NodeList selectNodeList(XPathContext xpathContext,
196: Node node, XPath xpath) throws TransformerException {
197: return getNodeList(evalXPath(xpathContext, node, xpath));
198: }
199:
200: /**
201: * Evaluates XPath to one node.
202: *
203: * @param xpathContext
204: * @param node xml node to be evaluated on
205: * @param expr XPath expression
206: * @return xml node
207: * @exception TransformerException
208: */
209: public static Node selectSingleNode(XPathContext xpathContext,
210: Node node, String expr) throws TransformerException {
211: NodeList nl = selectNodeList(xpathContext, node, expr);
212: if (nl.getLength() > 0)
213: return nl.item(0);
214: return null;
215: }
216:
217: /**
218: * Evaluates XPath to one node.
219: *
220: * @param xpathContext
221: * @param node xml node to be evaluated on
222: * @param xpath XPath expression
223: * @return xml node
224: * @exception TransformerException
225: */
226: public static Node selectSingleNode(XPathContext xpathContext,
227: Node node, XPath xpath) throws TransformerException {
228: NodeList nl = selectNodeList(xpathContext, node, xpath);
229: if (nl.getLength() > 0)
230: return nl.item(0);
231: return null;
232: }
233:
234: /**
235: * Converts result of XPath evaluation to nodelist.
236: *
237: * @param xo result of xpath evaluation
238: * @return nodelist
239: * @exception TransformerException
240: */
241: public static NodeList getNodeList(XObject xo)
242: throws TransformerException {
243: return xo.nodelist();
244: }
245:
246: /**
247: * Returns String representation of specified xml node.
248: *
249: * @param node the specified xml node
250: * @return string representation of the node
251: */
252: public static String getNodeData(Node node) {
253: switch (node.getNodeType()) {
254: case Node.DOCUMENT_FRAGMENT_NODE:
255: case Node.DOCUMENT_NODE:
256: case Node.ELEMENT_NODE: {
257: /*for (Node child = node.getFirstChild(); null != child;
258: child = child.getNextSibling())*/
259: Node child = node.getFirstChild();
260: if (child != null)
261: return getNodeData(child);
262: }
263: break;
264: case Node.TEXT_NODE:
265: case Node.CDATA_SECTION_NODE:
266: return node.getNodeValue();
267: case Node.ATTRIBUTE_NODE:
268: return node.getNodeValue();
269: case Node.PROCESSING_INSTRUCTION_NODE:
270: break;
271: default:
272: break;
273: }
274: return "";
275: }
276:
277: public static String getXObjectData(XObject xo) {
278: switch (xo.getType()) {
279: case XObject.CLASS_UNKNOWN:
280: return null;
281: case XObject.CLASS_BOOLEAN:
282: case XObject.CLASS_STRING:
283: case XObject.CLASS_NULL:
284: case XObject.CLASS_NUMBER:
285: case XObject.CLASS_UNRESOLVEDVARIABLE:
286: case XObject.CLASS_RTREEFRAG:
287: return xo.toString();
288: //break;
289: case XObject.CLASS_NODESET:
290: try {
291: NodeList nl = xo.nodelist();
292: StringBuffer sb = new StringBuffer();
293: int l = nl.getLength();
294: if (l == 0)
295: return null;
296: for (int i = 0; i < l; i++) {
297: Node node = nl.item(i);
298: sb.append(getNodeData(node));
299: }
300: return sb.toString();
301: } catch (javax.xml.transform.TransformerException e) {
302: }
303: }
304: return null;
305: //return xo.toString();
306: }
307:
308: public static void getNodeData(Node node, StringBuffer buf) {
309: switch (node.getNodeType()) {
310: case Node.DOCUMENT_FRAGMENT_NODE:
311: case Node.DOCUMENT_NODE:
312: case Node.ELEMENT_NODE: {
313: for (Node child = node.getFirstChild(); null != child; child = child
314: .getNextSibling()) {
315: buf.append('<');
316: buf.append(node.getNodeName());
317: buf.append('>');
318: getNodeData(child, buf);
319: buf.append("</");
320: buf.append(node.getNodeName());
321: buf.append('>');
322: }
323: }
324: break;
325: case Node.TEXT_NODE:
326: case Node.CDATA_SECTION_NODE:
327: buf.append(node.getNodeValue());
328: break;
329: case Node.ATTRIBUTE_NODE:
330: buf.append(node.getNodeValue());
331: break;
332: case Node.PROCESSING_INSTRUCTION_NODE:
333: // warning(XPATHErrorResources.WG_PARSING_AND_PREPARING);
334: break;
335: default:
336: // ignore
337: break;
338: }
339: }
340: }
|