public void testSubstringBeforeFunctionRequiresAtMostTwoArguments() throws JaxenException { BaseXPath xpath = new DOMXPath("substring-before('a', 'a', 'a')"); try { xpath.selectNodes(doc); fail("Allowed substring-before function with three arguments"); } catch (FunctionCallException ex) { assertNotNull(ex.getMessage()); } }
public void testNormalizeSpaceRequiresAtMostOneArguments() throws JaxenException { BaseXPath xpath = new DOMXPath("normalize-space('a', 'a')"); try { xpath.selectNodes(doc); fail("Allowed normalize-space function with two arguments"); } catch (FunctionCallException ex) { assertNotNull(ex.getMessage()); } }
public void testContainsFunctionRequiresAtLeastTwoArguments() throws JaxenException { BaseXPath xpath = new DOMXPath("contains('a')"); try { xpath.selectNodes(doc); fail("Allowed contains function with one argument"); } catch (FunctionCallException ex) { assertNotNull(ex.getMessage()); } }
@SuppressWarnings("unchecked") public static Iterator<Node> findNodes( Node node, String xpathquery, Map<String, String> namespaces) { Iterator<Node> it = null; try { BaseXPath expression = getXpath(xpathquery, namespaces); it = expression.selectNodes(node).iterator(); } catch (Exception exe) { } if (it == null) { it = new Vector().iterator(); } return it; }
private BaseXPath createXPath(String xpathQueryString, Navigator navigator) throws JaxenException { BaseXPath xpath = new BaseXPath(xpathQueryString, navigator); if (properties.size() > 1) { SimpleVariableContext vc = new SimpleVariableContext(); for (Entry<PropertyDescriptor<?>, Object> e : properties.entrySet()) { String propName = e.getKey().name(); if (!"xpath".equals(propName)) { Object value = e.getValue(); vc.setVariableValue(propName, value != null ? value.toString() : null); } } xpath.setVariableContext(vc); } return xpath; }
/** * Static saving of xpath queries reduces the compile time of the query up to 90%. A complete * XPath Query on a more then 100 line XML document will be up to 10 times faster, 0.1 ms instead * of 1 ms (core2duo) * * @param xpath * @param namespaces * @return * @throws JaxenException */ public static BaseXPath getXpath(String xpath, Map<String, String> namespaces) throws JaxenException { if (xpathCache.containsKey(xpath + namespaces.hashCode())) { return xpathCache.get(xpath + namespaces.hashCode()); } else { final BaseXPath expression = new DOMXPath(xpath); Set<Entry<String, String>> nsKeys = namespaces.entrySet(); for (Entry<String, String> entry : nsKeys) { expression.addNamespace(entry.getKey(), entry.getValue()); } if (xpathCache.size() > 20000) { log.info("Size of XPath Cache exceeded size of 20000, starting with new cache."); xpathCache = new HashMap<String, BaseXPath>(); } xpathCache.put(xpath + namespaces.hashCode(), expression); return expression; } }
@SuppressWarnings("unchecked") private void initializeXPathExpression(Navigator navigator) throws JaxenException { if (initializationStatus == InitializationStatus.FULL) { return; } else if (initializationStatus == InitializationStatus.PARTIAL && navigator == null) { if (LOG.isLoggable(Level.SEVERE)) { LOG.severe( "XPathRule is not initialized because no navigator was provided. " + "Please make sure to implement getXPathHandler in the handler of the language. " + "See also AbstractLanguageVersionHandler."); } return; } // // Attempt to use the RuleChain with this XPath query. To do so, the queries // should generally look like //TypeA or //TypeA | //TypeB. We will look at the // parsed XPath AST using the Jaxen APIs to make this determination. // If the query is not exactly what we are looking for, do not use the RuleChain. // nodeNameToXPaths = new HashMap<String, List<XPath>>(); BaseXPath originalXPath = createXPath(xpath, navigator); indexXPath(originalXPath, AST_ROOT); boolean useRuleChain = true; Stack<Expr> pending = new Stack<Expr>(); pending.push(originalXPath.getRootExpr()); while (!pending.isEmpty()) { Expr node = pending.pop(); // Need to prove we can handle this part of the query boolean valid = false; // Must be a LocationPath... that is something like //Type if (node instanceof LocationPath) { LocationPath locationPath = (LocationPath) node; if (locationPath.isAbsolute()) { // Should be at least two steps List<Step> steps = locationPath.getSteps(); if (steps.size() >= 2) { Step step1 = steps.get(0); Step step2 = steps.get(1); // First step should be an AllNodeStep using the descendant or self axis if (step1 instanceof AllNodeStep && ((AllNodeStep) step1).getAxis() == Axis.DESCENDANT_OR_SELF) { // Second step should be a NameStep using the child axis. if (step2 instanceof NameStep && ((NameStep) step2).getAxis() == Axis.CHILD) { // Construct a new expression that is appropriate for RuleChain use XPathFactory xpathFactory = new DefaultXPathFactory(); // Instead of an absolute location path, we'll be using a relative path LocationPath relativeLocationPath = xpathFactory.createRelativeLocationPath(); // The first step will be along the self axis Step allNodeStep = xpathFactory.createAllNodeStep(Axis.SELF); // Retain all predicates from the original name step for (Iterator<Predicate> i = step2.getPredicates().iterator(); i.hasNext(); ) { allNodeStep.addPredicate(i.next()); } relativeLocationPath.addStep(allNodeStep); // Retain the remaining steps from the original location path for (int i = 2; i < steps.size(); i++) { relativeLocationPath.addStep(steps.get(i)); } BaseXPath xpath = createXPath(relativeLocationPath.getText(), navigator); indexXPath(xpath, ((NameStep) step2).getLocalName()); valid = true; } } } } } else if (node instanceof UnionExpr) { // Or a UnionExpr, that is something like //TypeA | //TypeB UnionExpr unionExpr = (UnionExpr) node; pending.push(unionExpr.getLHS()); pending.push(unionExpr.getRHS()); valid = true; } if (!valid) { useRuleChain = false; break; } } if (useRuleChain) { // Use the RuleChain for all the nodes extracted from the xpath queries super.ruleChainVisits.addAll(nodeNameToXPaths.keySet()); } else { // Use original XPath if we cannot use the RuleChain nodeNameToXPaths.clear(); indexXPath(originalXPath, AST_ROOT); if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "Unable to use RuleChain for for XPath: " + xpath); } } if (navigator == null) { this.initializationStatus = InitializationStatus.PARTIAL; // Clear the node data, because we did not have a Navigator nodeNameToXPaths = null; } else { this.initializationStatus = InitializationStatus.FULL; } }