001 /*--------------------------------------------------------------------------+
002 $Id: XPathEvaluator.java 26700 2010-03-12 19:37:30Z hummelb $
003 | |
004 | Copyright 2005-2010 Technische Universitaet Muenchen |
005 | |
006 | Licensed 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 package edu.tum.cs.commons.xml;
019
020 import java.util.Iterator;
021 import java.util.List;
022
023 import javax.xml.namespace.NamespaceContext;
024 import javax.xml.namespace.QName;
025 import javax.xml.xpath.XPath;
026 import javax.xml.xpath.XPathConstants;
027 import javax.xml.xpath.XPathExpressionException;
028 import javax.xml.xpath.XPathFactory;
029
030 import org.w3c.dom.Element;
031 import org.w3c.dom.NodeList;
032
033 import edu.tum.cs.commons.assertion.CCSMAssert;
034 import edu.tum.cs.commons.collections.BidirectionalMap;
035
036 /**
037 * Evaluator for XPath expression. This is preferable to using the normal
038 * {@link XPath} class as it has built-in support for namespace-handling and the
039 * evaluation-method does not define exceptions.
040 *
041 * @author deissenb
042 * @author $Author:deissenb $
043 * @version $Rev: 26700 $
044 * @levd.rating GREEN Hash: F642A48694AB2CF2F48DB533F005C740
045 */
046 public class XPathEvaluator {
047
048 /** XPath object used to evaluate Bugzilla result document.s */
049 private final XPath xPath = XPathFactory.newInstance().newXPath();
050
051 /** The namespace context to use. */
052 private final NSContext nsContext;
053
054 /** Create new evaluator. */
055 public XPathEvaluator() {
056 nsContext = new NSContext();
057 xPath.setNamespaceContext(nsContext);
058 }
059
060 /** Add a namespace. */
061 public void addNamespace(String prefix, String uri) {
062 nsContext.addNamespace(prefix, uri);
063 }
064
065 /**
066 * Evaluates an XPath expression on context element. This assumes that the
067 * XPath expression is valid and raises an {@link AssertionError} otherwise.
068 *
069 * @param returnType
070 * use {@link XPathConstants} to define return type.
071 */
072 public Object select(String expr, Element context, QName returnType) {
073 try {
074 return xPath.evaluate(expr, context, returnType);
075 } catch (XPathExpressionException e) {
076 CCSMAssert.fail(e.getMessage());
077 return null;
078 }
079 }
080
081 /**
082 * Evaluates an XPath expression on context element. This assumes that the
083 * XPath expression is valid and raises an {@link AssertionError} otherwise.
084 */
085 public List<Element> selectList(String expr, Element context) {
086 return XMLUtils.elementNodes(selectNodeList(expr, context));
087 }
088
089 /**
090 * Evaluates an XPath expression on context element. This assumes that the
091 * XPath expression is valid and raises an {@link AssertionError} otherwise.
092 */
093 public NodeList selectNodeList(String expr, Element context) {
094 return (NodeList) select(expr, context, XPathConstants.NODESET);
095 }
096
097 /**
098 * Evaluates an XPath expression on context element. This assumes that the
099 * XPath expression is valid and raises an {@link AssertionError} otherwise.
100 */
101 public Element selectElement(String expr, Element context) {
102 return (Element) select(expr, context, XPathConstants.NODE);
103 }
104
105 /**
106 * Evaluates an XPath expression on context element. This assumes that the
107 * XPath expression is valid and raises an {@link AssertionError} otherwise.
108 */
109 public String selectString(String expr, Element context) {
110 return (String) select(expr, context, XPathConstants.STRING);
111 }
112
113 /**
114 * Evaluates an XPath expression on context element. This assumes that the
115 * XPath expression is valid and raises an {@link AssertionError} otherwise.
116 * Due to the implementation of {@link XPath} this returns 0.0 if the
117 * element was not found.
118 */
119 public double selectDouble(String expr, Element context) {
120 return (Double) select(expr, context, XPathConstants.NUMBER);
121 }
122
123 /**
124 * Evaluates an XPath expression on context element. This assumes that the
125 * XPath expression is valid and raises an {@link AssertionError} otherwise.
126 * Due to the implementation of {@link XPath} this returns 0 if the element
127 * was not found.
128 */
129 public int selectInt(String expr, Element context) {
130 return ((Double) select(expr, context, XPathConstants.NUMBER))
131 .intValue();
132 }
133
134 /**
135 * Evaluates an XPath expression on context element. This assumes that the
136 * XPath expression is valid and raises an {@link AssertionError} otherwise.
137 * Due to the implementation of {@link XPath} this returns
138 * <code>false</code> if the element was not found.
139 */
140 public boolean selectBoolean(String expr, Element context) {
141 return (Boolean) select(expr, context, XPathConstants.BOOLEAN);
142 }
143
144 /** Simple namespace context. */
145 private static class NSContext implements NamespaceContext {
146
147 /** Maps from prefix (first) to namespace URI (second). */
148 private final BidirectionalMap<String, String> map = new BidirectionalMap<String, String>();
149
150 /** Add new namespace to both maps. */
151 private void addNamespace(String prefix, String uri) {
152 map.put(prefix, uri);
153 }
154
155 /** {@inheritDoc} */
156 public String getNamespaceURI(String prefix) {
157 return map.getSecond(prefix);
158 }
159
160 /** {@inheritDoc} */
161 public String getPrefix(String namespaceURI) {
162 return map.getFirst(namespaceURI);
163 }
164
165 /** {@inheritDoc} */
166 @SuppressWarnings("unchecked")
167 public Iterator getPrefixes(String namespaceURI) {
168 return map.getFirstSet().iterator();
169 }
170 }
171 }