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 }