--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathExpressionImpl.java Mon Jan 26 12:17:59 2015 +0300
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathExpressionImpl.java Tue Jan 27 22:01:46 2015 -0800
@@ -1,15 +1,15 @@
/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
*/
/*
- * Copyright 1999-2004 The Apache Software Foundation.
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -17,36 +17,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-// $Id: XPathExpressionImpl.java,v 1.3 2005/09/27 09:40:43 sunithareddy Exp $
package com.sun.org.apache.xpath.internal.jaxp;
-import com.sun.org.apache.xpath.internal.*;
-import javax.xml.transform.TransformerException;
-
+import com.sun.org.apache.xalan.internal.utils.FeatureManager;
import com.sun.org.apache.xpath.internal.objects.XObject;
-import com.sun.org.apache.xml.internal.dtm.DTM;
-import com.sun.org.apache.xml.internal.utils.PrefixResolver;
-import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
-import com.sun.org.apache.xalan.internal.res.XSLMessages;
-import com.sun.org.apache.xalan.internal.utils.FactoryImpl;
-import com.sun.org.apache.xalan.internal.utils.FeatureManager;
-
-import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
+import javax.xml.transform.TransformerException;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathEvaluationResult;
+import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
-import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFunctionResolver;
import javax.xml.xpath.XPathVariableResolver;
-import javax.xml.xpath.XPathConstants;
-
+import org.w3c.dom.Document;
import org.w3c.dom.Node;
-import org.w3c.dom.Document;
-import org.w3c.dom.DOMImplementation;
-import org.w3c.dom.traversal.NodeIterator;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.DocumentBuilder;
-
import org.xml.sax.InputSource;
/**
@@ -54,21 +39,9 @@
*
* @author Ramesh Mandava
*/
-public class XPathExpressionImpl implements javax.xml.xpath.XPathExpression{
-
- private XPathFunctionResolver functionResolver;
- private XPathVariableResolver variableResolver;
- private JAXPPrefixResolver prefixResolver;
- private com.sun.org.apache.xpath.internal.XPath xpath;
+public class XPathExpressionImpl extends XPathImplUtil implements XPathExpression {
- // By default Extension Functions are allowed in XPath Expressions. If
- // Secure Processing Feature is set on XPathFactory then the invocation of
- // extensions function need to throw XPathFunctionException
- private boolean featureSecureProcessing = false;
-
- private boolean useServicesMechanism = true;
-
- private final FeatureManager featureManager;
+ private com.sun.org.apache.xpath.internal.XPath xpath;
/** Protected constructor to prevent direct instantiation; use compile()
* from the context.
@@ -81,7 +54,7 @@
protected XPathExpressionImpl(com.sun.org.apache.xpath.internal.XPath xpath,
JAXPPrefixResolver prefixResolver,
XPathFunctionResolver functionResolver,
- XPathVariableResolver variableResolver ) {
+ XPathVariableResolver variableResolver) {
this(xpath, prefixResolver, functionResolver, variableResolver,
false, true, new FeatureManager());
};
@@ -89,291 +62,108 @@
protected XPathExpressionImpl(com.sun.org.apache.xpath.internal.XPath xpath,
JAXPPrefixResolver prefixResolver,XPathFunctionResolver functionResolver,
XPathVariableResolver variableResolver, boolean featureSecureProcessing,
- boolean useServicesMechanism, FeatureManager featureManager ) {
+ boolean useServiceMechanism, FeatureManager featureManager) {
this.xpath = xpath;
this.prefixResolver = prefixResolver;
this.functionResolver = functionResolver;
this.variableResolver = variableResolver;
this.featureSecureProcessing = featureSecureProcessing;
- this.useServicesMechanism = useServicesMechanism;
+ this.useServiceMechanism = useServiceMechanism;
this.featureManager = featureManager;
};
- public void setXPath (com.sun.org.apache.xpath.internal.XPath xpath ) {
+ public void setXPath (com.sun.org.apache.xpath.internal.XPath xpath) {
this.xpath = xpath;
}
public Object eval(Object item, QName returnType)
throws javax.xml.transform.TransformerException {
- XObject resultObject = eval ( item );
- return getResultAsType( resultObject, returnType );
- }
-
- private XObject eval ( Object contextItem )
- throws javax.xml.transform.TransformerException {
- com.sun.org.apache.xpath.internal.XPathContext xpathSupport = null;
- if ( functionResolver != null ) {
- JAXPExtensionsProvider jep = new JAXPExtensionsProvider(
- functionResolver, featureSecureProcessing, featureManager );
- xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext( jep );
- } else {
- xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext();
- }
-
- xpathSupport.setVarStack(new JAXPVariableStack(variableResolver));
- XObject xobj = null;
-
- Node contextNode = (Node)contextItem;
- // We always need to have a ContextNode with Xalan XPath implementation
- // To allow simple expression evaluation like 1+1 we are setting
- // dummy Document as Context Node
-
- if ( contextNode == null )
- xobj = xpath.execute(xpathSupport, DTM.NULL, prefixResolver);
- else
- xobj = xpath.execute(xpathSupport, contextNode, prefixResolver);
-
- return xobj;
+ XObject resultObject = eval(item, xpath);
+ return getResultAsType(resultObject, returnType);
}
-
- /**
- * <p>Evaluate the compiled XPath expression in the specified context and
- * return the result as the specified type.</p>
- *
- * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
- *
- * <p>If <code>returnType</code> is not one of the types defined
- * in {@link XPathConstants},
- * then an <code>IllegalArgumentException</code> is thrown.</p>
- *
- * <p>If a <code>null</code> value is provided for
- * <code>item</code>, an empty document will be used for the
- * context.
- * If <code>returnType</code> is <code>null</code>, then a
- * <code>NullPointerException</code> is thrown.</p>
- *
- * @param item The starting context (node or node list, for example).
- * @param returnType The desired return type.
- *
- * @return The <code>Object</code> that is the result of evaluating the
- * expression and converting the result to
- * <code>returnType</code>.
- *
- * @throws XPathExpressionException If the expression cannot be evaluated.
- * @throws IllegalArgumentException If <code>returnType</code> is not one
- * of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If <code>returnType</code> is
- * <code>null</code>.
- */
+ @Override
public Object evaluate(Object item, QName returnType)
throws XPathExpressionException {
- //Validating parameters to enforce constraints defined by JAXP spec
- if ( returnType == null ) {
- //Throwing NullPointerException as defined in spec
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"returnType"} );
- throw new NullPointerException( fmsg );
- }
- // Checking if requested returnType is supported. returnType need to be
- // defined in XPathConstants
- if ( !isSupported ( returnType ) ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
- new Object[] { returnType.toString() } );
- throw new IllegalArgumentException ( fmsg );
- }
+ isSupported(returnType);
try {
- return eval( item, returnType);
- } catch ( java.lang.NullPointerException npe ) {
+ return eval(item, returnType);
+ } catch (java.lang.NullPointerException npe) {
// If VariableResolver returns null Or if we get
// NullPointerException at this stage for some other reason
// then we have to reurn XPathException
- throw new XPathExpressionException ( npe );
- } catch ( javax.xml.transform.TransformerException te ) {
+ throw new XPathExpressionException (npe);
+ } catch (javax.xml.transform.TransformerException te) {
Throwable nestedException = te.getException();
- if ( nestedException instanceof javax.xml.xpath.XPathFunctionException ) {
+ if (nestedException instanceof javax.xml.xpath.XPathFunctionException) {
throw (javax.xml.xpath.XPathFunctionException)nestedException;
} else {
// For any other exceptions we need to throw
- // XPathExpressionException ( as per spec )
- throw new XPathExpressionException( te);
+ // XPathExpressionException (as per spec)
+ throw new XPathExpressionException(te);
}
}
-
- }
-
- /**
- * <p>Evaluate the compiled XPath expression in the specified context and
- * return the result as a <code>String</code>.</p>
- *
- * <p>This method calls {@link #evaluate(Object item, QName returnType)}
- * with a <code>returnType</code> of
- * {@link XPathConstants#STRING}.</p>
- *
- * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
- *
- * <p>If a <code>null</code> value is provided for
- * <code>item</code>, an empty document will be used for the
- * context.
- *
- * @param item The starting context (node or node list, for example).
- *
- * @return The <code>String</code> that is the result of evaluating the
- * expression and converting the result to a
- * <code>String</code>.
- *
- * @throws XPathExpressionException If the expression cannot be evaluated.
- */
- public String evaluate(Object item)
- throws XPathExpressionException {
- return (String)this.evaluate( item, XPathConstants.STRING );
}
-
- static DocumentBuilderFactory dbf = null;
- static DocumentBuilder db = null;
- static Document d = null;
+ @Override
+ public String evaluate(Object item)
+ throws XPathExpressionException {
+ return (String)this.evaluate(item, XPathConstants.STRING);
+ }
- /**
- * <p>Evaluate the compiled XPath expression in the context of the
- * specified <code>InputSource</code> and return the result as the
- * specified type.</p>
- *
- * <p>This method builds a data model for the {@link InputSource} and calls
- * {@link #evaluate(Object item, QName returnType)} on the resulting
- * document object.</p>
- *
- * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
- *
- * <p>If <code>returnType</code> is not one of the types defined in
- * {@link XPathConstants},
- * then an <code>IllegalArgumentException</code> is thrown.</p>
- *
- *<p>If <code>source</code> or <code>returnType</code> is <code>null</code>,
- * then a <code>NullPointerException</code> is thrown.</p>
- *
- * @param source The <code>InputSource</code> of the document to evaluate
- * over.
- * @param returnType The desired return type.
- *
- * @return The <code>Object</code> that is the result of evaluating the
- * expression and converting the result to
- * <code>returnType</code>.
- *
- * @throws XPathExpressionException If the expression cannot be evaluated.
- * @throws IllegalArgumentException If <code>returnType</code> is not one
- * of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If <code>source</code> or
- * <code>returnType</code> is <code>null</code>.
- */
+ @Override
public Object evaluate(InputSource source, QName returnType)
throws XPathExpressionException {
- if ( ( source == null ) || ( returnType == null ) ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL,
- null );
- throw new NullPointerException ( fmsg );
- }
- // Checking if requested returnType is supported. returnType need to be
- // defined in XPathConstants
- if ( !isSupported ( returnType ) ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
- new Object[] { returnType.toString() } );
- throw new IllegalArgumentException ( fmsg );
- }
+ isSupported (returnType);
try {
- if ( dbf == null ) {
- dbf = FactoryImpl.getDOMFactory(useServicesMechanism);
- dbf.setNamespaceAware( true );
- dbf.setValidating( false );
- }
- db = dbf.newDocumentBuilder();
- Document document = db.parse( source );
- return eval( document, returnType );
- } catch ( Exception e ) {
- throw new XPathExpressionException ( e );
+ Document document = getDocument(source);
+ return eval(document, returnType);
+ } catch (TransformerException e) {
+ throw new XPathExpressionException(e);
}
}
- /**
- * <p>Evaluate the compiled XPath expression in the context of the specified <code>InputSource</code> and return the result as a
- * <code>String</code>.</p>
- *
- * <p>This method calls {@link #evaluate(InputSource source, QName returnType)} with a <code>returnType</code> of
- * {@link XPathConstants#STRING}.</p>
- *
- * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
- *
- * <p>If <code>source</code> is <code>null</code>, then a <code>NullPointerException</code> is thrown.</p>
- *
- * @param source The <code>InputSource</code> of the document to evaluate over.
- *
- * @return The <code>String</code> that is the result of evaluating the expression and converting the result to a
- * <code>String</code>.
- *
- * @throws XPathExpressionException If the expression cannot be evaluated.
- * @throws NullPointerException If <code>source</code> is <code>null</code>.
- */
+ @Override
public String evaluate(InputSource source)
throws XPathExpressionException {
- return (String)this.evaluate( source, XPathConstants.STRING );
+ return (String)this.evaluate(source, XPathConstants.STRING);
}
- private boolean isSupported( QName returnType ) {
- // XPathConstants.STRING
- if ( ( returnType.equals( XPathConstants.STRING ) ) ||
- ( returnType.equals( XPathConstants.NUMBER ) ) ||
- ( returnType.equals( XPathConstants.BOOLEAN ) ) ||
- ( returnType.equals( XPathConstants.NODE ) ) ||
- ( returnType.equals( XPathConstants.NODESET ) ) ) {
+ @Override
+ public <T>T evaluateExpression(Object item, Class<T> type)
+ throws XPathExpressionException {
+ isSupportedClassType(type);
- return true;
- }
- return false;
- }
+ try {
+ XObject resultObject = eval(item, xpath);
+ if (type.isAssignableFrom(XPathEvaluationResult.class)) {
+ return getXPathResult(resultObject, type);
+ } else {
+ return XPathResultImpl.getValue(resultObject, type);
+ }
- private Object getResultAsType( XObject resultObject, QName returnType )
- throws javax.xml.transform.TransformerException {
- // XPathConstants.STRING
- if ( returnType.equals( XPathConstants.STRING ) ) {
- return resultObject.str();
+ } catch (javax.xml.transform.TransformerException te) {
+ throw new XPathExpressionException(te);
}
- // XPathConstants.NUMBER
- if ( returnType.equals( XPathConstants.NUMBER ) ) {
- return new Double ( resultObject.num());
- }
- // XPathConstants.BOOLEAN
- if ( returnType.equals( XPathConstants.BOOLEAN ) ) {
- return new Boolean( resultObject.bool());
- }
- // XPathConstants.NODESET ---ORdered, UNOrdered???
- if ( returnType.equals( XPathConstants.NODESET ) ) {
- return resultObject.nodelist();
- }
- // XPathConstants.NODE
- if ( returnType.equals( XPathConstants.NODE ) ) {
- NodeIterator ni = resultObject.nodeset();
- //Return the first node, or null
- return ni.nextNode();
- }
- // If isSupported check is already done then the execution path
- // shouldn't come here. Being defensive
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
- new Object[] { returnType.toString()});
- throw new IllegalArgumentException ( fmsg );
}
+ @Override
+ public XPathEvaluationResult<?> evaluateExpression(Object item)
+ throws XPathExpressionException {
+ return evaluateExpression(item, XPathEvaluationResult.class);
+ }
+
+ @Override
+ public <T>T evaluateExpression(InputSource source, Class<T> type)
+ throws XPathExpressionException {
+ Document document = getDocument(source);
+ return evaluateExpression(document, type);
+ }
+
+ @Override
+ public XPathEvaluationResult<?> evaluateExpression(InputSource source)
+ throws XPathExpressionException {
+ return evaluateExpression(source, XPathEvaluationResult.class);
+ }
}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java Mon Jan 26 12:17:59 2015 +0300
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java Tue Jan 27 22:01:46 2015 -0800
@@ -1,6 +1,5 @@
/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Copyright 1999-2004 The Apache Software Foundation.
@@ -28,55 +27,37 @@
import javax.xml.xpath.XPathFunctionResolver;
import javax.xml.xpath.XPathVariableResolver;
import javax.xml.xpath.XPathExpression;
-
-import com.sun.org.apache.xml.internal.dtm.DTM;
import com.sun.org.apache.xpath.internal.*;
import com.sun.org.apache.xpath.internal.objects.XObject;
-import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
-import com.sun.org.apache.xalan.internal.res.XSLMessages;
-import com.sun.org.apache.xalan.internal.utils.FactoryImpl;
import com.sun.org.apache.xalan.internal.utils.FeatureManager;
-
-import org.w3c.dom.Node;
import org.w3c.dom.Document;
-import org.w3c.dom.traversal.NodeIterator;
-
import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-
-import javax.xml.parsers.*;
-
-import java.io.IOException;
+import javax.xml.transform.TransformerException;
+import javax.xml.xpath.XPathEvaluationResult;
/**
* The XPathImpl class provides implementation for the methods defined in
- * javax.xml.xpath.XPath interface. This provide simple access to the results
+ * javax.xml.xpath.XPath interface. This provides simple access to the results
* of an XPath expression.
*
- *
* @author Ramesh Mandava
+ *
+ * Updated 12/04/2014:
+ * New methods: evaluateExpression
+ * Refactored to share code with XPathExpressionImpl.
*/
-public class XPathImpl implements javax.xml.xpath.XPath {
+public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath {
// Private variables
- private XPathVariableResolver variableResolver;
- private XPathFunctionResolver functionResolver;
private XPathVariableResolver origVariableResolver;
private XPathFunctionResolver origFunctionResolver;
private NamespaceContext namespaceContext=null;
- private JAXPPrefixResolver prefixResolver;
- // By default Extension Functions are allowed in XPath Expressions. If
- // Secure Processing Feature is set on XPathFactory then the invocation of
- // extensions function need to throw XPathFunctionException
- private boolean featureSecureProcessing = false;
- private boolean useServiceMechanism = true;
- private final FeatureManager featureManager;
- XPathImpl( XPathVariableResolver vr, XPathFunctionResolver fr ) {
+ XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr) {
this(vr, fr, false, true, new FeatureManager());
}
- XPathImpl( XPathVariableResolver vr, XPathFunctionResolver fr,
+ XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr,
boolean featureSecureProcessing, boolean useServiceMechanism,
FeatureManager featureManager) {
this.origVariableResolver = this.variableResolver = vr;
@@ -86,451 +67,173 @@
this.featureManager = featureManager;
}
- /**
- * <p>Establishes a variable resolver.</p>
- *
- * @param resolver Variable Resolver
- */
+
+ //-Override-
public void setXPathVariableResolver(XPathVariableResolver resolver) {
- if ( resolver == null ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"XPathVariableResolver"} );
- throw new NullPointerException( fmsg );
- }
+ requireNonNull(resolver, "XPathVariableResolver");
this.variableResolver = resolver;
}
- /**
- * <p>Returns the current variable resolver.</p>
- *
- * @return Current variable resolver
- */
+ //-Override-
public XPathVariableResolver getXPathVariableResolver() {
return variableResolver;
}
- /**
- * <p>Establishes a function resolver.</p>
- *
- * @param resolver XPath function resolver
- */
+ //-Override-
public void setXPathFunctionResolver(XPathFunctionResolver resolver) {
- if ( resolver == null ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"XPathFunctionResolver"} );
- throw new NullPointerException( fmsg );
- }
+ requireNonNull(resolver, "XPathFunctionResolver");
this.functionResolver = resolver;
}
- /**
- * <p>Returns the current function resolver.</p>
- *
- * @return Current function resolver
- */
+ //-Override-
public XPathFunctionResolver getXPathFunctionResolver() {
return functionResolver;
}
- /**
- * <p>Establishes a namespace context.</p>
- *
- * @param nsContext Namespace context to use
- */
+ //-Override-
public void setNamespaceContext(NamespaceContext nsContext) {
- if ( nsContext == null ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"NamespaceContext"} );
- throw new NullPointerException( fmsg );
- }
+ requireNonNull(nsContext, "NamespaceContext");
this.namespaceContext = nsContext;
- this.prefixResolver = new JAXPPrefixResolver ( nsContext );
+ this.prefixResolver = new JAXPPrefixResolver (nsContext);
}
- /**
- * <p>Returns the current namespace context.</p>
- *
- * @return Current Namespace context
- */
+ //-Override-
public NamespaceContext getNamespaceContext() {
return namespaceContext;
}
- private static Document d = null;
-
- private DocumentBuilder getParser() {
- try {
- // we'd really like to cache those DocumentBuilders, but we can't because:
- // 1. thread safety. parsers are not thread-safe, so at least
- // we need one instance per a thread.
- // 2. parsers are non-reentrant, so now we are looking at having a
- // pool of parsers.
- // 3. then the class loading issue. The look-up procedure of
- // DocumentBuilderFactory.newInstance() depends on context class loader
- // and system properties, which may change during the execution of JVM.
- //
- // so we really have to create a fresh DocumentBuilder every time we need one
- // - KK
- DocumentBuilderFactory dbf = FactoryImpl.getDOMFactory(useServiceMechanism);
- dbf.setNamespaceAware( true );
- dbf.setValidating( false );
- return dbf.newDocumentBuilder();
- } catch (ParserConfigurationException e) {
- // this should never happen with a well-behaving JAXP implementation.
- throw new Error(e);
- }
- }
-
+ /**
+ * Evaluate an {@code XPath} expression in the specified context.
+ * @param expression The XPath expression.
+ * @param contextItem The starting context.
+ * @return an XObject as the result of evaluating the expression
+ * @throws TransformerException if evaluating fails
+ */
+ private XObject eval(String expression, Object contextItem)
+ throws TransformerException {
+ requireNonNull(expression, "XPath expression");
+ com.sun.org.apache.xpath.internal.XPath xpath = new com.sun.org.apache.xpath.internal.XPath(expression,
+ null, prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT);
- private XObject eval(String expression, Object contextItem)
- throws javax.xml.transform.TransformerException {
- com.sun.org.apache.xpath.internal.XPath xpath = new com.sun.org.apache.xpath.internal.XPath( expression,
- null, prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT );
- com.sun.org.apache.xpath.internal.XPathContext xpathSupport = null;
- if ( functionResolver != null ) {
- JAXPExtensionsProvider jep = new JAXPExtensionsProvider(
- functionResolver, featureSecureProcessing, featureManager );
- xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext( jep );
- } else {
- xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext();
- }
-
- XObject xobj = null;
-
- xpathSupport.setVarStack(new JAXPVariableStack(variableResolver));
-
- // If item is null, then we will create a a Dummy contextNode
- if ( contextItem instanceof Node ) {
- xobj = xpath.execute (xpathSupport, (Node)contextItem,
- prefixResolver );
- } else {
- xobj = xpath.execute ( xpathSupport, DTM.NULL, prefixResolver );
- }
-
- return xobj;
+ return eval(contextItem, xpath);
}
- /**
- * <p>Evaluate an <code>XPath</code> expression in the specified context and return the result as the specified type.</p>
- *
- * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and <code>QName</code> resolution and return type conversion.</p>
- *
- * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants} (
- * {@link XPathConstants#NUMBER NUMBER},
- * {@link XPathConstants#STRING STRING},
- * {@link XPathConstants#BOOLEAN BOOLEAN},
- * {@link XPathConstants#NODE NODE} or
- * {@link XPathConstants#NODESET NODESET})
- * then an <code>IllegalArgumentException</code> is thrown.</p>
- *
- * <p>If a <code>null</code> value is provided for
- * <code>item</code>, an empty document will be used for the
- * context.
- * If <code>expression</code> or <code>returnType</code> is <code>null</code>, then a
- * <code>NullPointerException</code> is thrown.</p>
- *
- * @param expression The XPath expression.
- * @param item The starting context (node or node list, for example).
- * @param returnType The desired return type.
- *
- * @return Result of evaluating an XPath expression as an <code>Object</code> of <code>returnType</code>.
- *
- * @throws XPathExpressionException If <code>expression</code> cannot be evaluated.
- * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If <code>expression</code> or <code>returnType</code> is <code>null</code>.
- */
+ //-Override-
public Object evaluate(String expression, Object item, QName returnType)
throws XPathExpressionException {
- if ( expression == null ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"XPath expression"} );
- throw new NullPointerException ( fmsg );
- }
- if ( returnType == null ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"returnType"} );
- throw new NullPointerException ( fmsg );
- }
- // Checking if requested returnType is supported. returnType need to
- // be defined in XPathConstants
- if ( !isSupported ( returnType ) ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
- new Object[] { returnType.toString() } );
- throw new IllegalArgumentException ( fmsg );
- }
+ //this check is necessary before calling eval to maintain binary compatibility
+ requireNonNull(expression, "XPath expression");
+ isSupported(returnType);
try {
- XObject resultObject = eval( expression, item );
- return getResultAsType( resultObject, returnType );
- } catch ( java.lang.NullPointerException npe ) {
+ XObject resultObject = eval(expression, item);
+ return getResultAsType(resultObject, returnType);
+ } catch (java.lang.NullPointerException npe) {
// If VariableResolver returns null Or if we get
// NullPointerException at this stage for some other reason
// then we have to reurn XPathException
- throw new XPathExpressionException ( npe );
- } catch ( javax.xml.transform.TransformerException te ) {
+ throw new XPathExpressionException (npe);
+ } catch (TransformerException te) {
Throwable nestedException = te.getException();
- if ( nestedException instanceof javax.xml.xpath.XPathFunctionException ) {
+ if (nestedException instanceof javax.xml.xpath.XPathFunctionException) {
throw (javax.xml.xpath.XPathFunctionException)nestedException;
} else {
// For any other exceptions we need to throw
- // XPathExpressionException ( as per spec )
- throw new XPathExpressionException ( te );
+ // XPathExpressionException (as per spec)
+ throw new XPathExpressionException (te);
}
}
}
- private boolean isSupported( QName returnType ) {
- if ( ( returnType.equals( XPathConstants.STRING ) ) ||
- ( returnType.equals( XPathConstants.NUMBER ) ) ||
- ( returnType.equals( XPathConstants.BOOLEAN ) ) ||
- ( returnType.equals( XPathConstants.NODE ) ) ||
- ( returnType.equals( XPathConstants.NODESET ) ) ) {
-
- return true;
- }
- return false;
- }
-
- private Object getResultAsType( XObject resultObject, QName returnType )
- throws javax.xml.transform.TransformerException {
- // XPathConstants.STRING
- if ( returnType.equals( XPathConstants.STRING ) ) {
- return resultObject.str();
- }
- // XPathConstants.NUMBER
- if ( returnType.equals( XPathConstants.NUMBER ) ) {
- return new Double ( resultObject.num());
- }
- // XPathConstants.BOOLEAN
- if ( returnType.equals( XPathConstants.BOOLEAN ) ) {
- return new Boolean( resultObject.bool());
- }
- // XPathConstants.NODESET ---ORdered, UNOrdered???
- if ( returnType.equals( XPathConstants.NODESET ) ) {
- return resultObject.nodelist();
- }
- // XPathConstants.NODE
- if ( returnType.equals( XPathConstants.NODE ) ) {
- NodeIterator ni = resultObject.nodeset();
- //Return the first node, or null
- return ni.nextNode();
- }
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
- new Object[] { returnType.toString()});
- throw new IllegalArgumentException( fmsg );
+ //-Override-
+ public String evaluate(String expression, Object item)
+ throws XPathExpressionException {
+ return (String)this.evaluate(expression, item, XPathConstants.STRING);
}
-
-
- /**
- * <p>Evaluate an XPath expression in the specified context and return the result as a <code>String</code>.</p>
- *
- * <p>This method calls {@link #evaluate(String expression, Object item, QName returnType)} with a <code>returnType</code> of
- * {@link XPathConstants#STRING}.</p>
- *
- * <p>See "Evaluation of XPath Expressions" of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
- *
- * <p>If a <code>null</code> value is provided for
- * <code>item</code>, an empty document will be used for the
- * context.
- * If <code>expression</code> is <code>null</code>, then a <code>NullPointerException</code> is thrown.</p>
- *
- * @param expression The XPath expression.
- * @param item The starting context (node or node list, for example).
- *
- * @return The <code>String</code> that is the result of evaluating the expression and
- * converting the result to a <code>String</code>.
- *
- * @throws XPathExpressionException If <code>expression</code> cannot be evaluated.
- * @throws NullPointerException If <code>expression</code> is <code>null</code>.
- */
- public String evaluate(String expression, Object item)
- throws XPathExpressionException {
- return (String)this.evaluate( expression, item, XPathConstants.STRING );
- }
-
- /**
- * <p>Compile an XPath expression for later evaluation.</p>
- *
- * <p>If <code>expression</code> contains any {@link XPathFunction}s,
- * they must be available via the {@link XPathFunctionResolver}.
- * An {@link XPathExpressionException} will be thrown if the <code>XPathFunction</code>
- * cannot be resovled with the <code>XPathFunctionResolver</code>.</p>
- *
- * <p>If <code>expression</code> is <code>null</code>, a <code>NullPointerException</code> is thrown.</p>
- *
- * @param expression The XPath expression.
- *
- * @return Compiled XPath expression.
-
- * @throws XPathExpressionException If <code>expression</code> cannot be compiled.
- * @throws NullPointerException If <code>expression</code> is <code>null</code>.
- */
+ //-Override-
public XPathExpression compile(String expression)
throws XPathExpressionException {
- if ( expression == null ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"XPath expression"} );
- throw new NullPointerException ( fmsg );
- }
+ requireNonNull(expression, "XPath expression");
try {
com.sun.org.apache.xpath.internal.XPath xpath = new XPath (expression, null,
- prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT );
+ prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT);
// Can have errorListener
XPathExpressionImpl ximpl = new XPathExpressionImpl (xpath,
prefixResolver, functionResolver, variableResolver,
- featureSecureProcessing, useServiceMechanism, featureManager );
+ featureSecureProcessing, useServiceMechanism, featureManager);
return ximpl;
- } catch ( javax.xml.transform.TransformerException te ) {
- throw new XPathExpressionException ( te ) ;
+ } catch (TransformerException te) {
+ throw new XPathExpressionException (te) ;
}
}
-
- /**
- * <p>Evaluate an XPath expression in the context of the specified <code>InputSource</code>
- * and return the result as the specified type.</p>
- *
- * <p>This method builds a data model for the {@link InputSource} and calls
- * {@link #evaluate(String expression, Object item, QName returnType)} on the resulting document object.</p>
- *
- * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
- *
- * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants},
- * then an <code>IllegalArgumentException</code> is thrown.</p>
- *
- * <p>If <code>expression</code>, <code>source</code> or <code>returnType</code> is <code>null</code>,
- * then a <code>NullPointerException</code> is thrown.</p>
- *
- * @param expression The XPath expression.
- * @param source The input source of the document to evaluate over.
- * @param returnType The desired return type.
- *
- * @return The <code>Object</code> that encapsulates the result of evaluating the expression.
- *
- * @throws XPathExpressionException If expression cannot be evaluated.
- * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If <code>expression</code>, <code>source</code> or <code>returnType</code>
- * is <code>null</code>.
- */
+ //-Override-
public Object evaluate(String expression, InputSource source,
QName returnType) throws XPathExpressionException {
- // Checking validity of different parameters
- if( source== null ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"source"} );
- throw new NullPointerException ( fmsg );
- }
- if ( expression == null ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"XPath expression"} );
- throw new NullPointerException ( fmsg );
- }
- if ( returnType == null ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"returnType"} );
- throw new NullPointerException ( fmsg );
- }
-
- //Checking if requested returnType is supported.
- //returnType need to be defined in XPathConstants
- if ( !isSupported ( returnType ) ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
- new Object[] { returnType.toString() } );
- throw new IllegalArgumentException ( fmsg );
- }
+ isSupported(returnType);
try {
-
- Document document = getParser().parse( source );
-
- XObject resultObject = eval( expression, document );
- return getResultAsType( resultObject, returnType );
- } catch ( SAXException e ) {
- throw new XPathExpressionException ( e );
- } catch( IOException e ) {
- throw new XPathExpressionException ( e );
- } catch ( javax.xml.transform.TransformerException te ) {
+ Document document = getDocument(source);
+ XObject resultObject = eval(expression, document);
+ return getResultAsType(resultObject, returnType);
+ } catch (TransformerException te) {
Throwable nestedException = te.getException();
- if ( nestedException instanceof javax.xml.xpath.XPathFunctionException ) {
+ if (nestedException instanceof javax.xml.xpath.XPathFunctionException) {
throw (javax.xml.xpath.XPathFunctionException)nestedException;
} else {
- throw new XPathExpressionException ( te );
+ throw new XPathExpressionException (te);
}
}
-
}
-
-
-
- /**
- * <p>Evaluate an XPath expression in the context of the specified <code>InputSource</code>
- * and return the result as a <code>String</code>.</p>
- *
- * <p>This method calls {@link #evaluate(String expression, InputSource source, QName returnType)} with a
- * <code>returnType</code> of {@link XPathConstants#STRING}.</p>
- *
- * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
- *
- * <p>If <code>expression</code> or <code>source</code> is <code>null</code>,
- * then a <code>NullPointerException</code> is thrown.</p>
- *
- * @param expression The XPath expression.
- * @param source The <code>InputSource</code> of the document to evaluate over.
- *
- * @return The <code>String</code> that is the result of evaluating the expression and
- * converting the result to a <code>String</code>.
- *
- * @throws XPathExpressionException If expression cannot be evaluated.
- * @throws NullPointerException If <code>expression</code> or <code>source</code> is <code>null</code>.
- */
+ //-Override-
public String evaluate(String expression, InputSource source)
throws XPathExpressionException {
- return (String)this.evaluate( expression, source, XPathConstants.STRING );
+ return (String)this.evaluate(expression, source, XPathConstants.STRING);
}
- /**
- * <p>Reset this <code>XPath</code> to its original configuration.</p>
- *
- * <p><code>XPath</code> is reset to the same state as when it was created with
- * {@link XPathFactory#newXPath()}.
- * <code>reset()</code> is designed to allow the reuse of existing <code>XPath</code>s
- * thus saving resources associated with the creation of new <code>XPath</code>s.</p>
- *
- * <p>The reset <code>XPath</code> is not guaranteed to have the same
- * {@link XPathFunctionResolver}, {@link XPathVariableResolver}
- * or {@link NamespaceContext} <code>Object</code>s, e.g. {@link Object#equals(Object obj)}.
- * It is guaranteed to have a functionally equal <code>XPathFunctionResolver</code>,
- * <code>XPathVariableResolver</code>
- * and <code>NamespaceContext</code>.</p>
- */
+ //-Override-
public void reset() {
this.variableResolver = this.origVariableResolver;
this.functionResolver = this.origFunctionResolver;
this.namespaceContext = null;
}
+ //-Override-
+ public <T> T evaluateExpression(String expression, Object item, Class<T> type)
+ throws XPathExpressionException {
+ isSupportedClassType(type);
+ try {
+ XObject resultObject = eval(expression, item);
+ if (type.isAssignableFrom(XPathEvaluationResult.class)) {
+ return getXPathResult(resultObject, type);
+ } else {
+ return XPathResultImpl.getValue(resultObject, type);
+ }
+ } catch (TransformerException te) {
+ throw new XPathExpressionException (te);
+ }
+ }
+
+ //-Override-
+ public XPathEvaluationResult<?> evaluateExpression(String expression, Object item)
+ throws XPathExpressionException {
+ return evaluateExpression(expression, item, XPathEvaluationResult.class);
+ }
+
+ //-Override-
+ public <T> T evaluateExpression(String expression, InputSource source, Class<T> type)
+ throws XPathExpressionException {
+ Document document = getDocument(source);
+ return evaluateExpression(expression, document, type);
+ }
+
+ //-Override-
+ public XPathEvaluationResult<?> evaluateExpression(String expression, InputSource source)
+ throws XPathExpressionException {
+ return evaluateExpression(expression, source, XPathEvaluationResult.class);
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java Tue Jan 27 22:01:46 2015 -0800
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.org.apache.xpath.internal.jaxp;
+
+import com.sun.org.apache.xalan.internal.res.XSLMessages;
+import com.sun.org.apache.xalan.internal.utils.FactoryImpl;
+import com.sun.org.apache.xalan.internal.utils.FeatureManager;
+import com.sun.org.apache.xml.internal.dtm.DTM;
+import com.sun.org.apache.xpath.internal.objects.XObject;
+import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
+import java.io.IOException;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathEvaluationResult;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFunctionResolver;
+import javax.xml.xpath.XPathNodes;
+import javax.xml.xpath.XPathVariableResolver;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.traversal.NodeIterator;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * This class contains several utility methods used by XPathImpl and
+ * XPathExpressionImpl
+ */
+class XPathImplUtil {
+ XPathFunctionResolver functionResolver;
+ XPathVariableResolver variableResolver;
+ JAXPPrefixResolver prefixResolver;
+ boolean useServiceMechanism = true;
+ // By default Extension Functions are allowed in XPath Expressions. If
+ // Secure Processing Feature is set on XPathFactory then the invocation of
+ // extensions function need to throw XPathFunctionException
+ boolean featureSecureProcessing = false;
+ FeatureManager featureManager;
+
+ /**
+ * Evaluate an XPath context using the internal XPath engine
+ * @param contextItem The XPath context
+ * @param xpath The internal XPath engine
+ * @return an XObject
+ * @throws javax.xml.transform.TransformerException If the expression cannot be evaluated.
+ */
+ XObject eval(Object contextItem, com.sun.org.apache.xpath.internal.XPath xpath)
+ throws javax.xml.transform.TransformerException {
+ com.sun.org.apache.xpath.internal.XPathContext xpathSupport;
+ if (functionResolver != null) {
+ JAXPExtensionsProvider jep = new JAXPExtensionsProvider(
+ functionResolver, featureSecureProcessing, featureManager);
+ xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext(jep);
+ } else {
+ xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext();
+ }
+
+ xpathSupport.setVarStack(new JAXPVariableStack(variableResolver));
+ XObject xobj;
+
+ Node contextNode = (Node)contextItem;
+ // We always need to have a ContextNode with Xalan XPath implementation
+ // To allow simple expression evaluation like 1+1 we are setting
+ // dummy Document as Context Node
+ if (contextNode == null) {
+ xobj = xpath.execute(xpathSupport, DTM.NULL, prefixResolver);
+ } else {
+ xobj = xpath.execute(xpathSupport, contextNode, prefixResolver);
+ }
+
+ return xobj;
+ }
+
+ /**
+ * Parse the input source and return a Document.
+ * @param source The {@code InputSource} of the document
+ * @return a DOM Document
+ * @throws XPathExpressionException if there is an error parsing the source.
+ */
+ Document getDocument(InputSource source)
+ throws XPathExpressionException {
+ requireNonNull(source, "Source");
+ try {
+ // we'd really like to cache those DocumentBuilders, but we can't because:
+ // 1. thread safety. parsers are not thread-safe, so at least
+ // we need one instance per a thread.
+ // 2. parsers are non-reentrant, so now we are looking at having a
+ // pool of parsers.
+ // 3. then the class loading issue. The look-up procedure of
+ // DocumentBuilderFactory.newInstance() depends on context class loader
+ // and system properties, which may change during the execution of JVM.
+ //
+ // so we really have to create a fresh DocumentBuilder every time we need one
+ // - KK
+ DocumentBuilderFactory dbf = FactoryImpl.getDOMFactory(useServiceMechanism);
+ dbf.setNamespaceAware(true);
+ dbf.setValidating(false);
+ return dbf.newDocumentBuilder().parse(source);
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+ throw new XPathExpressionException (e);
+ }
+ }
+
+ /**
+ * Get result depending on the QName type defined in XPathConstants
+ * @param resultObject the result of an evaluation
+ * @param returnType the return type
+ * @return result per the return type
+ * @throws TransformerException if the result can not be converted to
+ * the specified return type.
+ */
+ Object getResultAsType(XObject resultObject, QName returnType)
+ throws TransformerException {
+ // XPathConstants.STRING
+ if (returnType.equals(XPathConstants.STRING)) {
+ return resultObject.str();
+ }
+ // XPathConstants.NUMBER
+ if (returnType.equals(XPathConstants.NUMBER)) {
+ return resultObject.num();
+ }
+ // XPathConstants.BOOLEAN
+ if (returnType.equals(XPathConstants.BOOLEAN)) {
+ return resultObject.bool();
+ }
+ // XPathConstants.NODESET ---ORdered, UNOrdered???
+ if (returnType.equals(XPathConstants.NODESET)) {
+ return resultObject.nodelist();
+ }
+ // XPathConstants.NODE
+ if (returnType.equals(XPathConstants.NODE)) {
+ NodeIterator ni = resultObject.nodeset();
+ //Return the first node, or null
+ return ni.nextNode();
+ }
+ // If isSupported check is already done then the execution path
+ // shouldn't come here. Being defensive
+ String fmsg = XSLMessages.createXPATHMessage(
+ XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
+ new Object[] { returnType.toString()});
+ throw new IllegalArgumentException (fmsg);
+ }
+
+ /**
+ * Construct an XPathExpressionResult object based on the result of the
+ * evaluation and cast to the specified class type.
+ * @param <T> The class type
+ * @param resultObject the result of an evaluation
+ * @param type The class type expected to be returned by the XPath expression.
+ * @return an instance of the specified type or null if the XObject returned
+ * an UNKNOWN object type.
+ * @throws TransformerException if there is an error converting the result
+ * to the specified type. It's unlikely to happen. This is mostly needed
+ * by the internal XPath engine.
+ */
+ <T> T getXPathResult(XObject resultObject, Class<T> type)
+ throws TransformerException {
+ int resultType = resultObject.getType();
+
+ switch (resultType) {
+ case XObject.CLASS_BOOLEAN :
+ return type.cast(new XPathResultImpl<>(resultObject, Boolean.class));
+ case XObject.CLASS_NUMBER :
+ return type.cast(new XPathResultImpl<>(resultObject, Double.class));
+ case XObject.CLASS_STRING :
+ return type.cast(new XPathResultImpl<>(resultObject, String.class));
+ case XObject.CLASS_NODESET :
+ return type.cast(new XPathResultImpl<>(resultObject, XPathNodes.class));
+ case XObject.CLASS_RTREEFRAG : //NODE
+ return type.cast(new XPathResultImpl<>(resultObject, Node.class));
+ }
+
+ return null;
+ }
+
+ /**
+ * Check whether or not the specified type is supported
+ * @param <T> The class type
+ * @param type The type to be checked
+ * @throws IllegalArgumentException if the type is not supported
+ */
+ <T> void isSupportedClassType(Class<T> type) {
+ requireNonNull(type, "The class type");
+ if (type.isAssignableFrom(Boolean.class) ||
+ type.isAssignableFrom(Double.class) ||
+ type.isAssignableFrom(Integer.class) ||
+ type.isAssignableFrom(Long.class) ||
+ type.isAssignableFrom(String.class) ||
+ type.isAssignableFrom(XPathNodes.class) ||
+ type.isAssignableFrom(Node.class) ||
+ type.isAssignableFrom(XPathEvaluationResult.class)) {
+ return;
+ }
+ String fmsg = XSLMessages.createXPATHMessage(
+ XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
+ new Object[] { type.toString() });
+ throw new IllegalArgumentException (fmsg);
+ }
+
+ /**
+ * Check if the requested returnType is supported.
+ * @param returnType the return type
+ * @throws IllegalArgumentException if the return type is not supported
+ */
+ void isSupported(QName returnType) {
+ requireNonNull(returnType, "returnType");
+ if (returnType.equals(XPathConstants.STRING) ||
+ returnType.equals(XPathConstants.NUMBER) ||
+ returnType.equals(XPathConstants.BOOLEAN) ||
+ returnType.equals(XPathConstants.NODE) ||
+ returnType.equals(XPathConstants.NODESET)) {
+ return;
+ }
+ String fmsg = XSLMessages.createXPATHMessage(
+ XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
+ new Object[] { returnType.toString() });
+ throw new IllegalArgumentException (fmsg);
+ }
+
+ /**
+ * Checks that the specified parameter is not {@code null}.
+ *
+ * @param <T> the type of the reference
+ * @param param the parameter to check for nullity
+ * @param paramName the parameter name
+ * @throws NullPointerException if {@code param} is {@code null}
+ */
+ <T> void requireNonNull(T param, String paramName) {
+ if (param == null) {
+ String fmsg = XSLMessages.createXPATHMessage(
+ XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
+ new Object[] {paramName});
+ throw new NullPointerException (fmsg);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathNodesImpl.java Tue Jan 27 22:01:46 2015 -0800
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.org.apache.xpath.internal.jaxp;
+
+import java.util.Iterator;
+import javax.xml.xpath.XPathException;
+import javax.xml.xpath.XPathNodes;
+import javax.xml.xpath.XPathEvaluationResult.XPathResultType;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * This class implements XPathNodes that represents a set of nodes selected by
+ * evaluating an expression.
+ */
+public class XPathNodesImpl implements XPathNodes {
+ Class<Node> elementType;
+ NodeList nodeList = null;
+
+ public XPathNodesImpl(NodeList nodeList, Class<Node> elementType) {
+ this.nodeList = nodeList;
+ this.elementType = elementType;
+ }
+
+ @Override
+ public Iterator<Node> iterator() {
+ return new NodeSetIterator<>(elementType);
+ }
+
+ class NodeSetIterator<E> implements Iterator<E> {
+ int currentIndex;
+ Class<E> elementType;
+ NodeSetIterator(Class<E> elementType) {
+ this.elementType = elementType;
+ }
+ public boolean hasNext() {
+ if (nodeList != null) {
+ return currentIndex < nodeList.getLength();
+ }
+
+ return false;
+ }
+
+ public E next() {
+ if (nodeList != null && nodeList.getLength() > 0) {
+ return elementType.cast(nodeList.item(currentIndex++));
+ }
+ return null;
+ }
+ }
+
+ @Override
+ public int size() {
+ if (nodeList != null) {
+ return nodeList.getLength();
+ }
+ return 0;
+ }
+
+ @Override
+ public Node get(int index) throws XPathException {
+ if (index <0 || index >= size()) {
+ throw new IndexOutOfBoundsException("Index " + index + " is out of bounds");
+ }
+ if (nodeList != null) {
+ return nodeList.item(index);
+ }
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathResultImpl.java Tue Jan 27 22:01:46 2015 -0800
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.org.apache.xpath.internal.jaxp;
+
+import com.sun.org.apache.xpath.internal.objects.XObject;
+import java.util.Objects;
+import javax.xml.transform.TransformerException;
+import javax.xml.xpath.XPathNodes;
+import javax.xml.xpath.XPathEvaluationResult;
+import javax.xml.xpath.XPathEvaluationResult.XPathResultType;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.traversal.NodeIterator;
+
+
+/**
+ * This is the implementation of XPathEvaluationResult that represents the
+ * result of the evaluation of an XPath expression within the context of a
+ * particular node.
+ */
+class XPathResultImpl<T> implements XPathEvaluationResult<T> {
+
+ XObject resultObject;
+ int resultType;
+ Class<T> type;
+ XPathResultType mapToType;
+ NodeList nodeList = null;
+ int currentIndex;
+ Node currentNode;
+
+ boolean boolValue = false;
+ Node node = null;
+ double numValue;
+ String strValue;
+
+ /**
+ * Construct an XPathEvaluationResult object.
+ *
+ * @param resultObject internal XPath result object
+ * @param type class type
+ * @throws TransformerException if there is an error reading the XPath
+ * result.
+ */
+ public XPathResultImpl(XObject resultObject, Class<T> type)
+ throws TransformerException {
+ this.resultObject = resultObject;
+ resultType = resultObject.getType();
+ this.type = type;
+ getResult(resultObject);
+ }
+
+ /**
+ * Return the result type as an enum specified by {@code XPathResultType}
+ * @return the result type
+ */
+ @Override
+ public XPathResultType type() {
+ return mapToType;
+ }
+
+ /**
+ * Returns the value of the result as the type <T> specified for the class.
+ *
+ * @return The value of the result.
+ */
+ @Override
+ public T value() {
+ Objects.requireNonNull(type);
+ try {
+ return getValue(resultObject, type);
+ } catch (TransformerException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /**
+ * Read the XObject and set values in accordance with the result type
+ * @param resultObject internal XPath result object
+ * @throws TransformerException if there is an error reading the XPath
+ * result.
+ */
+ private void getResult(XObject resultObject) throws TransformerException {
+ switch (resultType) {
+ case XObject.CLASS_BOOLEAN:
+ boolValue = resultObject.bool();
+ mapToType = XPathResultType.BOOLEAN;
+ break;
+ case XObject.CLASS_NUMBER:
+ numValue = resultObject.num();
+ mapToType = XPathResultType.NUMBER;
+ break;
+ case XObject.CLASS_STRING:
+ strValue = resultObject.str();
+ mapToType = XPathResultType.STRING;
+ break;
+ case XObject.CLASS_NODESET:
+ mapToType = XPathResultType.NODESET;
+ nodeList = resultObject.nodelist();
+ break;
+ case XObject.CLASS_RTREEFRAG: //NODE
+ mapToType = XPathResultType.NODE;
+ NodeIterator ni = resultObject.nodeset();
+ //Return the first node, or null
+ node = ni.nextNode();
+ break;
+ }
+ }
+
+ /**
+ * Read the internal result object and return the value in accordance with
+ * the type specified.
+ *
+ * @param <T> The expected class type.
+ * @param resultObject internal XPath result object
+ * @param type the class type
+ * @return The value of the result, null in case of unexpected type.
+ * @throws TransformerException if there is an error reading the XPath
+ * result.
+ */
+ static <T> T getValue(XObject resultObject, Class<T> type) throws TransformerException {
+ Objects.requireNonNull(type);
+ if (type.isAssignableFrom(XPathEvaluationResult.class)) {
+ return type.cast(new XPathResultImpl<T>(resultObject, type));
+ }
+ int resultType = classToInternalType(type);
+ switch (resultType) {
+ case XObject.CLASS_BOOLEAN:
+ return type.cast(resultObject.bool());
+ case XObject.CLASS_NUMBER:
+ if (Double.class.isAssignableFrom(type)) {
+ return type.cast(resultObject.num());
+ } else if (Integer.class.isAssignableFrom(type)) {
+ return type.cast((int)resultObject.num());
+ } else if (Long.class.isAssignableFrom(type)) {
+ return type.cast((long)resultObject.num());
+ }
+ /*
+ This is to suppress warnings. By the current specification,
+ among numeric types, only Double, Integer and Long are supported.
+ */
+ break;
+ case XObject.CLASS_STRING:
+ return type.cast(resultObject.str());
+ case XObject.CLASS_NODESET:
+ XPathNodes nodeSet = new XPathNodesImpl(resultObject.nodelist(),
+ Node.class);
+ return type.cast(nodeSet);
+ case XObject.CLASS_RTREEFRAG: //NODE
+ NodeIterator ni = resultObject.nodeset();
+ //Return the first node, or null
+ return type.cast(ni.nextNode());
+ }
+
+ return null;
+ }
+
+ /**
+ * Map the specified class type to the internal result type
+ *
+ * @param <T> The expected class type.
+ * @param type the class type
+ * @return the internal XObject type.
+ */
+ static <T> int classToInternalType(Class<T> type) {
+ if (type.isAssignableFrom(Boolean.class)) {
+ return XObject.CLASS_BOOLEAN;
+ } else if (Number.class.isAssignableFrom(type)) {
+ return XObject.CLASS_NUMBER;
+ } else if (type.isAssignableFrom(String.class)) {
+ return XObject.CLASS_STRING;
+ } else if (type.isAssignableFrom(XPathNodes.class)) {
+ return XObject.CLASS_NODESET;
+ } else if (type.isAssignableFrom(Node.class)) {
+ return XObject.CLASS_RTREEFRAG;
+ }
+ return XObject.CLASS_NULL;
+ }
+}
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPath.java Mon Jan 26 12:17:59 2015 +0300
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPath.java Tue Jan 27 22:01:46 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,12 +25,12 @@
package javax.xml.xpath;
-import org.xml.sax.InputSource;
+import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
-import javax.xml.namespace.NamespaceContext;
+import org.xml.sax.InputSource;
/**
- * <p><code>XPath</code> provides access to the XPath evaluation environment and expressions.</p>
+ * {@code XPath} provides access to the XPath evaluation environment and expressions.
*
* <a name="XPath-evaluation"/>
* <table border="1" cellpadding="2">
@@ -39,7 +39,6 @@
* <th colspan="2">Evaluation of XPath Expressions.</th>
* </tr>
* </thead>
- * <tbody>
* <tr>
* <td>context</td>
* <td>
@@ -55,8 +54,8 @@
* If the expression contains a variable reference, its value will be found through the {@link XPathVariableResolver}
* set with {@link #setXPathVariableResolver(XPathVariableResolver resolver)}.
* An {@link XPathExpressionException} is raised if the variable resolver is undefined or
- * the resolver returns <code>null</code> for the variable.
- * The value of a variable must be immutable through the course of any single evaluation.</p>
+ * the resolver returns {@code null} for the variable.
+ * The value of a variable must be immutable through the course of any single evaluation.
* </td>
* </tr>
* <tr>
@@ -65,7 +64,7 @@
* If the expression contains a function reference, the function will be found through the {@link XPathFunctionResolver}
* set with {@link #setXPathFunctionResolver(XPathFunctionResolver resolver)}.
* An {@link XPathExpressionException} is raised if the function resolver is undefined or
- * the function resolver returns <code>null</code> for the function.</p>
+ * the function resolver returns {@code null} for the function.
* </td>
* </tr>
* <tr>
@@ -80,7 +79,7 @@
* <td>
* This result of evaluating an expression is converted to an instance of the desired return type.
* Valid return types are defined in {@link XPathConstants}.
- * Conversion to the return type follows XPath conversion rules.</p>
+ * Conversion to the return type follows XPath conversion rules.
* </td>
* </tr>
* </table>
@@ -88,9 +87,9 @@
* <p>An XPath object is not thread-safe and not reentrant.
* In other words, it is the application's responsibility to make
* sure that one {@link XPath} object is not used from
- * more than one thread at any given time, and while the <code>evaluate</code>
+ * more than one thread at any given time, and while the {@code evaluate}
* method is invoked, applications may not recursively call
- * the <code>evaluate</code> method.
+ * the {@code evaluate} method.
* <p>
*
* @author <a href="Norman.Walsh@Sun.com">Norman Walsh</a>
@@ -100,191 +99,189 @@
*/
public interface XPath {
- /**
- * <p>Reset this <code>XPath</code> to its original configuration.</p>
- *
- * <p><code>XPath</code> is reset to the same state as when it was created with
- * {@link XPathFactory#newXPath()}.
- * <code>reset()</code> is designed to allow the reuse of existing <code>XPath</code>s
- * thus saving resources associated with the creation of new <code>XPath</code>s.</p>
- *
- * <p>The reset <code>XPath</code> is not guaranteed to have the same {@link XPathFunctionResolver}, {@link XPathVariableResolver}
- * or {@link NamespaceContext} <code>Object</code>s, e.g. {@link Object#equals(Object obj)}.
- * It is guaranteed to have a functionally equal <code>XPathFunctionResolver</code>, <code>XPathVariableResolver</code>
- * and <code>NamespaceContext</code>.</p>
- */
- public void reset();
/**
- * <p>Establish a variable resolver.</p>
+ * Reset this {@code XPath} to its original configuration.
+ *
+ * <p>{@code XPath} is reset to the same state as when it was created with
+ * {@link XPathFactory#newXPath()}.
+ * {@code reset()} is designed to allow the reuse of existing {@code XPath}s
+ * thus saving resources associated with the creation of new {@code XPath}s.
*
- * <p>A <code>NullPointerException</code> is thrown if <code>resolver</code> is <code>null</code>.</p>
+ * <p>The reset {@code XPath} is not guaranteed to have the same
+ * {@link XPathFunctionResolver}, {@link XPathVariableResolver}
+ * or {@link NamespaceContext} {@code Object}s, e.g. {@link Object#equals(Object obj)}.
+ * It is guaranteed to have a functionally equal {@code XPathFunctionResolver},
+ * {@code XPathVariableResolver} and {@code NamespaceContext}.
+ */
+ public void reset();
+
+ /**
+ * Establish a variable resolver.
+ *
+ * <p>A {@code NullPointerException} is thrown if {@code resolver} is {@code null}.
*
* @param resolver Variable resolver.
*
- * @throws NullPointerException If <code>resolver</code> is <code>null</code>.
+ * @throws NullPointerException If {@code resolver} is {@code null}.
*/
public void setXPathVariableResolver(XPathVariableResolver resolver);
/**
- * <p>Return the current variable resolver.</p>
+ * Return the current variable resolver.
*
- * <p><code>null</code> is returned in no variable resolver is in effect.</p>
+ * <p>{@code null} is returned in no variable resolver is in effect.
*
* @return Current variable resolver.
*/
public XPathVariableResolver getXPathVariableResolver();
/**
- * <p>Establish a function resolver.</p>
+ * Establish a function resolver.
*
- * <p>A <code>NullPointerException</code> is thrown if <code>resolver</code> is <code>null</code>.</p>
+ * <p>A {@code NullPointerException} is thrown if {@code resolver} is {@code null}.
*
* @param resolver XPath function resolver.
*
- * @throws NullPointerException If <code>resolver</code> is <code>null</code>.
+ * @throws NullPointerException If {@code resolver} is {@code null}.
*/
public void setXPathFunctionResolver(XPathFunctionResolver resolver);
/**
- * <p>Return the current function resolver.</p>
- *
- * <p><code>null</code> is returned in no function resolver is in effect.</p>
+ * Return the current function resolver.
+ * <p>
+ * {@code null} is returned in no function resolver is in effect.
*
* @return Current function resolver.
*/
public XPathFunctionResolver getXPathFunctionResolver();
/**
- * <p>Establish a namespace context.</p>
+ * Establish a namespace context.
*
- * <p>A <code>NullPointerException</code> is thrown if <code>nsContext</code> is <code>null</code>.</p>
+ * <p>A {@code NullPointerException} is thrown if {@code nsContext} is {@code null}.
*
* @param nsContext Namespace context to use.
*
- * @throws NullPointerException If <code>nsContext</code> is <code>null</code>.
+ * @throws NullPointerException If {@code nsContext} is {@code null}.
*/
public void setNamespaceContext(NamespaceContext nsContext);
/**
- * <p>Return the current namespace context.</p>
+ * Return the current namespace context.
*
- * <p><code>null</code> is returned in no namespace context is in effect.</p>
+ * <p>{@code null} is returned in no namespace context is in effect.
*
* @return Current Namespace context.
*/
public NamespaceContext getNamespaceContext();
/**
- * <p>Compile an XPath expression for later evaluation.</p>
+ * Compile an XPath expression for later evaluation.
*
- * <p>If <code>expression</code> contains any {@link XPathFunction}s,
+ * <p>If {@code expression} contains any {@link XPathFunction}s,
* they must be available via the {@link XPathFunctionResolver}.
* An {@link XPathExpressionException} will be thrown if the
- * <code>XPathFunction</code>
- * cannot be resovled with the <code>XPathFunctionResolver</code>.</p>
+ * {@code XPathFunction}
+ * cannot be resovled with the {@code XPathFunctionResolver}.
*
- * <p>If <code>expression</code> contains any variables, the
+ * <p>If {@code expression} contains any variables, the
* {@link XPathVariableResolver} in effect
- * <strong>at compile time</strong> will be used to resolve them.</p>
- *
- * <p>If <code>expression</code> is <code>null</code>, a <code>NullPointerException</code> is thrown.</p>
+ * <strong>at compile time</strong> will be used to resolve them.
*
* @param expression The XPath expression.
*
* @return Compiled XPath expression.
- * @throws XPathExpressionException If <code>expression</code> cannot be compiled.
- * @throws NullPointerException If <code>expression</code> is <code>null</code>.
+ * @throws XPathExpressionException If {@code expression} cannot be compiled.
+ * @throws NullPointerException If {@code expression} is {@code null}.
*/
public XPathExpression compile(String expression)
throws XPathExpressionException;
/**
- * <p>Evaluate an <code>XPath</code> expression in the specified context and return the result as the specified type.</p>
+ * Evaluate an {@code XPath} expression in the specified context and
+ * return the result as the specified type.
*
- * <p>See <a href="#XPath-evaluation">Evaluation of XPath Expressions</a> for context item evaluation,
- * variable, function and <code>QName</code> resolution and return type conversion.</p>
+ * <p>
+ * See <a href="#XPath-evaluation">Evaluation of XPath Expressions</a>
+ * for context item evaluation, variable, function and {@code QName} resolution
+ * and return type conversion.
+ * <p>
+ * The parameter {@code item} represents the context the XPath expression
+ * will be operated on. The type of the context is implementation-dependent.
+ * If the value is {@code null}, the operation must have no dependency on
+ * the context, otherwise an XPathExpressionException will be thrown.
*
- * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants} (
+ * @implNote
+ * The type of the context is usually {@link org.w3c.dom.Node}.
+ *
+ * @param expression The XPath expression.
+ * @param item The context the XPath expression will be evaluated in.
+ * @param returnType The result type expected to be returned by the XPath expression.
+ *
+ * @return The result of evaluating an XPath expression as an {@code Object} of {@code returnType}.
+ *
+ * @throws XPathExpressionException If {@code expression} cannot be evaluated.
+ * @throws IllegalArgumentException If {@code returnType} is not one of the types defined in {@link XPathConstants} (
* {@link XPathConstants#NUMBER NUMBER},
* {@link XPathConstants#STRING STRING},
* {@link XPathConstants#BOOLEAN BOOLEAN},
* {@link XPathConstants#NODE NODE} or
- * {@link XPathConstants#NODESET NODESET})
- * then an <code>IllegalArgumentException</code> is thrown.</p>
- *
- * <p>If a <code>null</code> value is provided for
- * <code>item</code>, an empty document will be used for the
- * context.
- * If <code>expression</code> or <code>returnType</code> is <code>null</code>, then a
- * <code>NullPointerException</code> is thrown.</p>
- *
- * @param expression The XPath expression.
- * @param item The starting context (a node, for example).
- * @param returnType The desired return type.
- *
- * @return Result of evaluating an XPath expression as an <code>Object</code> of <code>returnType</code>.
- *
- * @throws XPathExpressionException If <code>expression</code> cannot be evaluated.
- * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If <code>expression</code> or <code>returnType</code> is <code>null</code>.
+ * {@link XPathConstants#NODESET NODESET}).
+ * @throws NullPointerException If {@code expression or returnType} is {@code null}.
*/
public Object evaluate(String expression, Object item, QName returnType)
throws XPathExpressionException;
/**
- * <p>Evaluate an XPath expression in the specified context and return the result as a <code>String</code>.</p>
+ * Evaluate an XPath expression in the specified context and return the result as a {@code String}.
*
- * <p>This method calls {@link #evaluate(String expression, Object item, QName returnType)} with a <code>returnType</code> of
- * {@link XPathConstants#STRING}.</p>
+ * <p>This method calls {@link #evaluate(String expression, Object item, QName returnType)} with a {@code returnType} of
+ * {@link XPathConstants#STRING}.
*
* <p>See <a href="#XPath-evaluation">Evaluation of XPath Expressions</a> for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
+ * variable, function and QName resolution and return type conversion.
*
- * <p>If a <code>null</code> value is provided for
- * <code>item</code>, an empty document will be used for the
- * context.
- * If <code>expression</code> is <code>null</code>, then a <code>NullPointerException</code> is thrown.</p>
+ * <p>
+ * The parameter {@code item} represents the context the XPath expression
+ * will be operated on. The type of the context is implementation-dependent.
+ * If the value is {@code null}, the operation must have no dependency on
+ * the context, otherwise an XPathExpressionException will be thrown.
+ *
+ * @implNote
+ * The type of the context is usually {@link org.w3c.dom.Node}.
*
* @param expression The XPath expression.
- * @param item The starting context (a node, for example).
+ * @param item The context the XPath expression will be evaluated in.
*
- * @return The <code>String</code> that is the result of evaluating the expression and
- * converting the result to a <code>String</code>.
+ * @return The result of evaluating an XPath expression as a {@code String}.
*
- * @throws XPathExpressionException If <code>expression</code> cannot be evaluated.
- * @throws NullPointerException If <code>expression</code> is <code>null</code>.
+ * @throws XPathExpressionException If {@code expression} cannot be evaluated.
+ * @throws NullPointerException If {@code expression} is {@code null}.
*/
public String evaluate(String expression, Object item)
throws XPathExpressionException;
/**
- * <p>Evaluate an XPath expression in the context of the specified <code>InputSource</code>
- * and return the result as the specified type.</p>
+ * Evaluate an XPath expression in the context of the specified {@code InputSource}
+ * and return the result as the specified type.
*
* <p>This method builds a data model for the {@link InputSource} and calls
- * {@link #evaluate(String expression, Object item, QName returnType)} on the resulting document object.</p>
+ * {@link #evaluate(String expression, Object item, QName returnType)} on the resulting document object.
*
* <p>See <a href="#XPath-evaluation">Evaluation of XPath Expressions</a> for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
- *
- * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants},
- * then an <code>IllegalArgumentException</code> is thrown.</p>
- *
- * <p>If <code>expression</code>, <code>source</code> or <code>returnType</code> is <code>null</code>,
- * then a <code>NullPointerException</code> is thrown.</p>
+ * variable, function and QName resolution and return type conversion.
*
* @param expression The XPath expression.
* @param source The input source of the document to evaluate over.
* @param returnType The desired return type.
*
- * @return The <code>Object</code> that encapsulates the result of evaluating the expression.
+ * @return The {@code Object} that encapsulates the result of evaluating the expression.
*
* @throws XPathExpressionException If expression cannot be evaluated.
- * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If <code>expression</code>, <code>source</code> or <code>returnType</code>
- * is <code>null</code>.
+ * @throws IllegalArgumentException If {@code returnType} is not one of the types defined in {@link XPathConstants}.
+ * @throws NullPointerException If {@code expression, source or returnType} is {@code null}.
*/
public Object evaluate(
String expression,
@@ -293,27 +290,209 @@
throws XPathExpressionException;
/**
- * <p>Evaluate an XPath expression in the context of the specified <code>InputSource</code>
- * and return the result as a <code>String</code>.</p>
+ * Evaluate an XPath expression in the context of the specified {@code InputSource}
+ * and return the result as a {@code String}.
*
* <p>This method calls {@link #evaluate(String expression, InputSource source, QName returnType)} with a
- * <code>returnType</code> of {@link XPathConstants#STRING}.</p>
+ * {@code returnType} of {@link XPathConstants#STRING}.
*
* <p>See <a href="#XPath-evaluation">Evaluation of XPath Expressions</a> for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
- *
- * <p>If <code>expression</code> or <code>source</code> is <code>null</code>,
- * then a <code>NullPointerException</code> is thrown.</p>
+ * variable, function and QName resolution and return type conversion.
*
* @param expression The XPath expression.
- * @param source The <code>InputSource</code> of the document to evaluate over.
+ * @param source The {@code InputSource} of the document to evaluate over.
*
- * @return The <code>String</code> that is the result of evaluating the expression and
- * converting the result to a <code>String</code>.
+ * @return The {@code String} that is the result of evaluating the expression and
+ * converting the result to a {@code String}.
*
* @throws XPathExpressionException If expression cannot be evaluated.
- * @throws NullPointerException If <code>expression</code> or <code>source</code> is <code>null</code>.
+ * @throws NullPointerException If {@code expression or source} is {@code null}.
*/
public String evaluate(String expression, InputSource source)
throws XPathExpressionException;
+
+ /**
+ * Evaluate an XPath expression in the specified context and return
+ * the result with the type specified through the {@code class type}
+ *
+ * <p>
+ * The parameter {@code item} represents the context the XPath expression
+ * will be operated on. The type of the context is implementation-dependent.
+ * If the value is {@code null}, the operation must have no dependency on
+ * the context, otherwise an XPathExpressionException will be thrown.
+ *
+ * @implNote
+ * The type of the context is usually {@link org.w3c.dom.Node}.
+ *
+ * @implSpec
+ * The default implementation in the XPath API is equivalent to:
+ * <pre> {@code
+ * (T)evaluate(expression, item,
+ * XPathEvaluationResult.XPathResultType.getQNameType(type));
+ * }</pre>
+ *
+ * Since the {@code evaluate} method does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type, specifying
+ * XPathEvaluationResult as the type will result in IllegalArgumentException.
+ * Any implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must override
+ * this method.
+ *
+ * @param <T> The class type that will be returned by the XPath expression.
+ * @param expression The XPath expression.
+ * @param item The context the XPath expression will be evaluated in.
+ * @param type The class type expected to be returned by the XPath expression.
+ *
+ * @return The result of evaluating the expression.
+ *
+ * @throws XPathExpressionException If the expression cannot be evaluated.
+ * @throws IllegalArgumentException If {@code type} is not of the types
+ * corresponding to the types defined in the {@link XPathEvaluationResult.XPathResultType},
+ * or XPathEvaluationResult is specified as the type but an implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type is not available.
+ * @throws NullPointerException If {@code expression or type} is {@code null}.
+ *
+ * @since 1.9
+ */
+ default <T>T evaluateExpression(String expression, Object item, Class<T> type)
+ throws XPathExpressionException {
+ return type.cast(evaluate(expression, item,
+ XPathEvaluationResult.XPathResultType.getQNameType(type)));
+ }
+
+ /**
+ * Evaluate an XPath expression in the specified context. This is equivalent to
+ * calling {@link #evaluateExpression(String expression, Object item, Class type)}
+ * with type {@link XPathEvaluationResult}:
+ * <pre> {@code
+ * evaluateExpression(expression, item, XPathEvaluationResult.class);
+ * }</pre>
+ * <p>
+ * The parameter {@code item} represents the context the XPath expression
+ * will be operated on. The type of the context is implementation-dependent.
+ * If the value is {@code null}, the operation must have no dependency on
+ * the context, otherwise an XPathExpressionException will be thrown.
+ *
+ * @implNote
+ * The type of the context is usually {@link org.w3c.dom.Node}.
+ *
+ * @implSpec
+ * The default implementation in the XPath API is equivalent to:
+ * <pre> {@code
+ * evaluateExpression(expression, item, XPathEvaluationResult.class);
+ * }</pre>
+ *
+ * Since the {@code evaluate} method does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY}
+ * type, the default implementation of this method will always throw an
+ * IllegalArgumentException. Any implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must therefore
+ * override this method.
+ *
+ * @param expression The XPath expression.
+ * @param item The context the XPath expression will be evaluated in.
+ *
+ * @return The result of evaluating the expression.
+ *
+ * @throws XPathExpressionException If the expression cannot be evaluated.
+ * @throws IllegalArgumentException If the implementation of this method
+ * does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type.
+ * @throws NullPointerException If {@code expression} is {@code null}.
+ *
+ * @since 1.9
+ */
+ default XPathEvaluationResult<?> evaluateExpression(String expression, Object item)
+ throws XPathExpressionException
+ {
+ return evaluateExpression(expression, item, XPathEvaluationResult.class);
+ }
+
+ /**
+ * Evaluate an XPath expression in the context of the specified {@code source}
+ * and return the result as specified.
+ * <p>
+ * This method builds a data model for the {@link InputSource} and calls
+ * {@link #evaluateExpression(String expression, Object item, Class type)}
+ * on the resulting document object. The data model is usually
+ * {@link org.w3c.dom.Document}
+ *
+ * @implSpec
+ * The default implementation in the XPath API is equivalent to:
+ * <pre> {@code
+ (T)evaluate(expression, source,
+ XPathEvaluationResult.XPathResultType.getQNameType(type));
+ * }</pre>
+ *
+ * Since the {@code evaluate} method does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type, specifying
+ * XPathEvaluationResult as the type will result in IllegalArgumentException.
+ * Any implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must override
+ * this method.
+ *
+ * @param <T> The class type that will be returned by the XPath expression.
+ * @param expression The XPath expression.
+ * @param source The input source of the document to evaluate over.
+ * @param type The class type expected to be returned by the XPath expression.
+ *
+ * @return The result of evaluating the expression.
+ *
+ * @throws XPathExpressionException If the expression cannot be evaluated.
+ * @throws IllegalArgumentException If {@code type} is not of the types
+ * corresponding to the types defined in the {@link XPathEvaluationResult.XPathResultType
+ * XPathResultType}, or XPathEvaluationResult is specified as the type but an
+ * implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type is not available.
+ * @throws NullPointerException If {@code expression, source or type}is {@code null}.
+ *
+ * @since 1.9
+ */
+ default <T>T evaluateExpression(String expression, InputSource source, Class<T> type)
+ throws XPathExpressionException
+ {
+ return type.cast(evaluate(expression, source,
+ XPathEvaluationResult.XPathResultType.getQNameType(type)));
+ }
+
+ /**
+ * Evaluate an XPath expression in the specified context. This is equivalent to
+ * calling {@link #evaluateExpression(String expression, Object item, Class type)}
+ * with type {@link XPathEvaluationResult}:
+ * <pre> {@code
+ * evaluateExpression(expression, item, XPathEvaluationResult.class);
+ * }</pre>
+ * <p>
+ *
+ * @implSpec
+ * The default implementation in the XPath API is equivalent to:
+ * <pre> {@code
+ * evaluateExpression(expression, source, XPathEvaluationResult.class);
+ * }</pre>
+ *
+ * Since the {@code evaluate} method does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY}
+ * type, the default implementation of this method will always throw an
+ * IllegalArgumentException. Any implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must therefore
+ * override this method.
+ *
+ * @param expression The XPath expression.
+ * @param source The input source of the document to evaluate over.
+ *
+ * @return The result of evaluating the expression.
+ *
+ * @throws XPathExpressionException If the expression cannot be evaluated.
+ * @throws IllegalArgumentException If the implementation of this method
+ * does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type.
+ * @throws NullPointerException If {@code expression or source} is {@code null}.
+ *
+ * @since 1.9
+ */
+ default XPathEvaluationResult<?> evaluateExpression(String expression, InputSource source)
+ throws XPathExpressionException
+ {
+ return evaluateExpression(expression, source, XPathEvaluationResult.class);
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathEvaluationResult.java Tue Jan 27 22:01:46 2015 -0800
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package javax.xml.xpath;
+
+import java.util.Objects;
+import javax.xml.namespace.QName;
+import org.w3c.dom.Node;
+/**
+ * The {@code XPathEvaluationResult} interface represents the result of the
+ * evaluation of an XPath expression within the context of a particular node.
+ * The evaluation of an XPath expression can result in various result types as
+ * defined in XML Path Language (XPath) Version 1.0.
+ * <p>
+ *
+ * @param <T> the object type returned by the XPath evaluation.
+ * @see <a href="http://www.w3.org/TR/xpath">XML Path Language (XPath) Version
+ * 1.0</a>
+ *
+ * @since 1.9
+ */
+public interface XPathEvaluationResult<T> {
+
+ /**
+ * XPathResultType represents possible return types of an XPath evaluation.
+ * Provided as an enum type, it allows the use of switch statement. At the
+ * same time, a mapping is provided between the original QName types in
+ * {@link XPathConstants} and class types used in the generic methods.
+ */
+ public static enum XPathResultType {
+ /**
+ * Any type that represents any of the 5 other types listed below.
+ * Maps to {@link XPathEvaluationResult}.
+ */
+ ANY(new QName("http://www.w3.org/1999/XSL/Transform", "any"), XPathEvaluationResult.class),
+ /**
+ * The XPath 1.0 boolean data type. Maps to Java {@link Boolean}.
+ */
+ BOOLEAN(XPathConstants.BOOLEAN, Boolean.class),
+ /**
+ * The XPath 1.0 Number data type. Maps to Java {@link Number}. Of the
+ * subtypes of Number, only Double, Integer and Long are required.
+ */
+ NUMBER(XPathConstants.NUMBER, Number.class),
+ /**
+ * The XPath 1.0 String data type. Maps to Java {@link String}.
+ */
+ STRING(XPathConstants.STRING, String.class),
+ /**
+ * The XPath 1.0 NodeSet data type. Maps to {@link org.w3c.dom.NodeList}.
+ */
+ NODESET(XPathConstants.NODESET, XPathNodes.class),
+ /**
+ * The XPath 1.0 NodeSet data type. Maps to {@link org.w3c.dom.Node}.
+ */
+ NODE(XPathConstants.NODE, Node.class);
+
+ final QName qnameType;
+ final Class<?> clsType;
+ XPathResultType(QName qnameType, Class<?> clsType) {
+ this.qnameType = qnameType;
+ this.clsType = clsType;
+ }
+
+ /**
+ * Compares this type to the specified class type.
+ * @param clsType class type
+ * @return true if the argument is not null and is a class type that
+ * matches that this type represents, false otherwise.
+ */
+ private boolean equalsClassType(Class<?> clsType) {
+ Objects.nonNull(clsType);
+ if (clsType.isAssignableFrom(this.clsType)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the QName type as specified in {@link XPathConstants} that
+ * corresponds to the specified class type.
+ * @param clsType a class type that the enum type supports
+ * @return the QName type that matches with the specified class type,
+ * null if there is no match
+ */
+ static public QName getQNameType(Class<?> clsType) {
+ for (XPathResultType type : XPathResultType.values()) {
+ if (type.equalsClassType(clsType)) {
+ return type.qnameType;
+ }
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Return the result type as an enum specified by {@code XPathResultType}
+ * @return the result type
+ */
+ public XPathResultType type();
+
+ /**
+ * Returns the value of the result as the type <T> specified for the class.
+ *
+ * @return The value of the result.
+ */
+ public T value();
+
+}
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathExpression.java Mon Jan 26 12:17:59 2015 +0300
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathExpression.java Tue Jan 27 22:01:46 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,11 +25,11 @@
package javax.xml.xpath;
+import javax.xml.namespace.QName;
import org.xml.sax.InputSource;
-import javax.xml.namespace.QName;
/**
- * <p><code>XPathExpression</code> provides access to compiled XPath expressions.</p>
+ * <p>{@code XPathExpression} provides access to compiled XPath expressions.</p>
*
* <a name="XPathExpression-evaluation"/>
* <table border="1" cellpadding="2">
@@ -53,7 +53,7 @@
* <td>
* If the expression contains a variable reference, its value will be found through the {@link XPathVariableResolver}.
* An {@link XPathExpressionException} is raised if the variable resolver is undefined or
- * the resolver returns <code>null</code> for the variable.
+ * the resolver returns {@code null} for the variable.
* The value of a variable must be immutable through the course of any single evaluation.</p>
* </td>
* </tr>
@@ -62,7 +62,7 @@
* <td>
* If the expression contains a function reference, the function will be found through the {@link XPathFunctionResolver}.
* An {@link XPathExpressionException} is raised if the function resolver is undefined or
- * the function resolver returns <code>null</code> for the function.</p>
+ * the function resolver returns {@code null} for the function.</p>
* </td>
* </tr>
* <tr>
@@ -84,9 +84,9 @@
* <p>An XPath expression is not thread-safe and not reentrant.
* In other words, it is the application's responsibility to make
* sure that one {@link XPathExpression} object is not used from
- * more than one thread at any given time, and while the <code>evaluate</code>
+ * more than one thread at any given time, and while the {@code evaluate}
* method is invoked, applications may not recursively call
- * the <code>evaluate</code> method.
+ * the {@code evaluate} method.
* <p>
*
* @author <a href="mailto:Norman.Walsh@Sun.com">Norman Walsh</a>
@@ -96,50 +96,56 @@
*/
public interface XPathExpression {
+
/**
* <p>Evaluate the compiled XPath expression in the specified context and return the result as the specified type.</p>
*
* <p>See <a href="#XPathExpression-evaluation">Evaluation of XPath Expressions</a> for context item evaluation,
* variable, function and QName resolution and return type conversion.</p>
*
- * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants},
- * then an <code>IllegalArgumentException</code> is thrown.</p>
+ * <p>
+ * The parameter {@code item} represents the context the XPath expression
+ * will be operated on. The type of the context is implementation-dependent.
+ * If the value is {@code null}, the operation must have no dependency on
+ * the context, otherwise an XPathExpressionException will be thrown.
*
- * <p>If a <code>null</code> value is provided for
- * <code>item</code>, an empty document will be used for the
- * context.
- * If <code>returnType</code> is <code>null</code>, then a <code>NullPointerException</code> is thrown.</p>
+ * @implNote
+ * The type of the context is usually {@link org.w3c.dom.Node}.
*
- * @param item The starting context (a node, for example).
- * @param returnType The desired return type.
+ * @param item The context the XPath expression will be evaluated in.
+ * @param returnType The result type expected to be returned by the XPath expression.
*
- * @return The <code>Object</code> that is the result of evaluating the expression and converting the result to
- * <code>returnType</code>.
+ * @return The {@code Object} that is the result of evaluating the expression and converting the result to
+ * {@code returnType}.
*
* @throws XPathExpressionException If the expression cannot be evaluated.
- * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If <code>returnType</code> is <code>null</code>.
+ * @throws IllegalArgumentException If {@code returnType} is not one of the types defined in {@link XPathConstants}.
+ * @throws NullPointerException If {@code returnType} is {@code null}.
*/
public Object evaluate(Object item, QName returnType)
throws XPathExpressionException;
/**
- * <p>Evaluate the compiled XPath expression in the specified context and return the result as a <code>String</code>.</p>
+ * <p>Evaluate the compiled XPath expression in the specified context and return the result as a {@code String}.</p>
*
- * <p>This method calls {@link #evaluate(Object item, QName returnType)} with a <code>returnType</code> of
+ * <p>This method calls {@link #evaluate(Object item, QName returnType)} with a {@code returnType} of
* {@link XPathConstants#STRING}.</p>
*
* <p>See <a href="#XPathExpression-evaluation">Evaluation of XPath Expressions</a> for context item evaluation,
* variable, function and QName resolution and return type conversion.</p>
*
- * <p>If a <code>null</code> value is provided for
- * <code>item</code>, an empty document will be used for the
- * context.
+ * <p>
+ * The parameter {@code item} represents the context the XPath expression
+ * will be operated on. The type of the context is implementation-dependent.
+ * If the value is {@code null}, the operation must have no dependency on
+ * the context, otherwise an XPathExpressionException will be thrown.
*
- * @param item The starting context (a node, for example).
+ * @implNote
+ * The type of the context is usually {@link org.w3c.dom.Node}.
*
- * @return The <code>String</code> that is the result of evaluating the expression and converting the result to a
- * <code>String</code>.
+ * @param item The context the XPath expression will be evaluated in.
+ *
+ * @return The result of evaluating an XPath expression as a {@code String}.
*
* @throws XPathExpressionException If the expression cannot be evaluated.
*/
@@ -147,7 +153,7 @@
throws XPathExpressionException;
/**
- * <p>Evaluate the compiled XPath expression in the context of the specified <code>InputSource</code> and return the result as the
+ * <p>Evaluate the compiled XPath expression in the context of the specified {@code InputSource} and return the result as the
* specified type.</p>
*
* <p>This method builds a data model for the {@link InputSource} and calls
@@ -156,45 +162,225 @@
* <p>See <a href="#XPathExpression-evaluation">Evaluation of XPath Expressions</a> for context item evaluation,
* variable, function and QName resolution and return type conversion.</p>
*
- * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants},
- * then an <code>IllegalArgumentException</code> is thrown.</p>
+ * <p>If {@code returnType} is not one of the types defined in {@link XPathConstants},
+ * then an {@code IllegalArgumentException} is thrown.</p>
*
- * <p>If <code>source</code> or <code>returnType</code> is <code>null</code>,
- * then a <code>NullPointerException</code> is thrown.</p>
+ * <p>If {@code source} or {@code returnType} is {@code null},
+ * then a {@code NullPointerException} is thrown.</p>
*
- * @param source The <code>InputSource</code> of the document to evaluate over.
+ * @param source The {@code InputSource} of the document to evaluate over.
* @param returnType The desired return type.
*
- * @return The <code>Object</code> that is the result of evaluating the expression and converting the result to
- * <code>returnType</code>.
+ * @return The {@code Object} that is the result of evaluating the expression and converting the result to
+ * {@code returnType}.
*
* @throws XPathExpressionException If the expression cannot be evaluated.
- * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If <code>source</code> or <code>returnType</code> is <code>null</code>.
+ * @throws IllegalArgumentException If {@code returnType} is not one of the types defined in {@link XPathConstants}.
+ * @throws NullPointerException If {@code source or returnType} is {@code null}.
*/
public Object evaluate(InputSource source, QName returnType)
throws XPathExpressionException;
/**
- * <p>Evaluate the compiled XPath expression in the context of the specified <code>InputSource</code> and return the result as a
- * <code>String</code>.</p>
+ * <p>Evaluate the compiled XPath expression in the context of the specified {@code InputSource} and return the result as a
+ * {@code String}.</p>
*
- * <p>This method calls {@link #evaluate(InputSource source, QName returnType)} with a <code>returnType</code> of
+ * <p>This method calls {@link #evaluate(InputSource source, QName returnType)} with a {@code returnType} of
* {@link XPathConstants#STRING}.</p>
*
* <p>See <a href="#XPathExpression-evaluation">Evaluation of XPath Expressions</a> for context item evaluation,
* variable, function and QName resolution and return type conversion.</p>
*
- * <p>If <code>source</code> is <code>null</code>, then a <code>NullPointerException</code> is thrown.</p>
+ * <p>If {@code source} is {@code null}, then a {@code NullPointerException} is thrown.</p>
*
- * @param source The <code>InputSource</code> of the document to evaluate over.
+ * @param source The {@code InputSource} of the document to evaluate over.
*
- * @return The <code>String</code> that is the result of evaluating the expression and converting the result to a
- * <code>String</code>.
+ * @return The {@code String} that is the result of evaluating the expression and converting the result to a
+ * {@code String}.
*
* @throws XPathExpressionException If the expression cannot be evaluated.
- * @throws NullPointerException If <code>source</code> is <code>null</code>.
+ * @throws NullPointerException If {@code source} is {@code null}.
*/
public String evaluate(InputSource source)
throws XPathExpressionException;
+
+ /**
+ * Evaluate the compiled XPath expression in the specified context, and return
+ * the result with the type specified through the {@code class type}.
+ *
+ * <p>
+ * The parameter {@code item} represents the context the XPath expression
+ * will be operated on. The type of the context is implementation-dependent.
+ * If the value is {@code null}, the operation must have no dependency on
+ * the context, otherwise an XPathExpressionException will be thrown.
+ *
+ * @implNote
+ * The type of the context is usually {@link org.w3c.dom.Node}.
+ *
+ * @implSpec
+ * The default implementation in the XPath API is equivalent to:
+ * <pre> {@code
+ * (T)evaluate(item, XPathEvaluationResult.XPathResultType.getQNameType(type));
+ * }</pre>
+ *
+ * Since the {@code evaluate} method does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type, specifying
+ * XPathEvaluationResult as the type will result in IllegalArgumentException.
+ * Any implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must override
+ * this method.
+ *
+ * @param <T> The class type that will be returned by the XPath expression.
+ * @param item The context the XPath expression will be evaluated in.
+ * @param type The class type expected to be returned by the XPath expression.
+ *
+ * @return The result of evaluating the expression.
+ *
+ * @throws XPathExpressionException If the expression cannot be evaluated.
+ * @throws IllegalArgumentException If {@code type} is not of the types
+ * corresponding to the types defined in the {@link XPathEvaluationResult.XPathResultType
+ * XPathResultType}, or XPathEvaluationResult is specified as the type but an
+ * implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type is not available.
+ * @throws NullPointerException If {@code type} is {@code null}.
+ *
+ * @since 1.9
+ */
+ default <T>T evaluateExpression(Object item, Class<T> type)
+ throws XPathExpressionException
+ {
+ return type.cast(evaluate(item, XPathEvaluationResult.XPathResultType.getQNameType(type)));
+ }
+
+ /**
+ * Evaluate the compiled XPath expression in the specified context. This is
+ * equivalent to calling {@link #evaluateExpression(Object item, Class type)}
+ * with type {@link XPathEvaluationResult}:
+ * <pre> {@code
+ * evaluateExpression(item, XPathEvaluationResult.class);
+ * }</pre>
+ * <p>
+ * The parameter {@code item} represents the context the XPath expression
+ * will be operated on. The type of the context is implementation-dependent.
+ * If the value is {@code null}, the operation must have no dependency on
+ * the context, otherwise an XPathExpressionException will be thrown.
+ *
+ * @implNote
+ * The type of the context is usually {@link org.w3c.dom.Node}.
+ *
+ * @implSpec
+ * The default implementation in the XPath API is equivalent to:
+ * <pre> {@code
+ * evaluateExpression(item, XPathEvaluationResult.class);
+ * }</pre>
+ *
+ * Since the {@code evaluate} method does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY}
+ * type, the default implementation of this method will always throw an
+ * IllegalArgumentException. Any implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must therefore
+ * override this method.
+ *
+ * @param item The context the XPath expression will be evaluated in.
+ *
+ * @return The result of evaluating the expression.
+ *
+ * @throws XPathExpressionException If the expression cannot be evaluated.
+ * @throws IllegalArgumentException If the implementation of this method
+ * does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type.
+ *
+ * @since 1.9
+ */
+ default XPathEvaluationResult<?> evaluateExpression(Object item)
+ throws XPathExpressionException
+ {
+ return evaluateExpression(item, XPathEvaluationResult.class);
+ }
+
+ /**
+ * Evaluate the compiled XPath expression in the specified context,
+ * and return the result with the type specified through the {@code class type}
+ * <p>
+ * This method builds a data model for the {@link InputSource} and calls
+ * {@link #evaluateExpression(Object item, Class type)} on the resulting
+ * document object.
+ * <P>
+ * By default, the JDK's data model is {@link org.w3c.dom.Document}.
+ *
+ * @implSpec
+ * The default implementation in the XPath API is equivalent to:
+ * <pre> {@code
+ (T)evaluate(source, XPathEvaluationResult.XPathResultType.getQNameType(type));
+ * }</pre>
+ *
+ * Since the {@code evaluate} method does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type, specifying
+ * XPathEvaluationResult as the type will result in IllegalArgumentException.
+ * Any implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must override
+ * this method.
+ *
+ * @param <T> The class type that will be returned by the XPath expression.
+ * @param source The {@code InputSource} of the document to evaluate over.
+ * @param type The class type expected to be returned by the XPath expression.
+ *
+ * @return The result of evaluating the expression.
+ *
+ * @throws XPathExpressionException If the expression cannot be evaluated.
+ * @throws IllegalArgumentException If {@code type} is not of the types
+ * corresponding to the types defined in the {@link XPathEvaluationResult.XPathResultType
+ * XPathResultType}, or XPathEvaluationResult is specified as the type but an
+ * implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type
+ * is not available.
+ * @throws NullPointerException If {@code source or type} is {@code null}.
+ *
+ * @since 1.9
+ */
+ default <T>T evaluateExpression(InputSource source, Class<T> type)
+ throws XPathExpressionException
+ {
+ return type.cast(evaluate(source, XPathEvaluationResult.XPathResultType.getQNameType(type)));
+ }
+
+ /**
+ * Evaluate the compiled XPath expression in the specified context. This is
+ * equivalent to calling {@link #evaluateExpression(InputSource source, Class type)}
+ * with type {@link XPathEvaluationResult}:
+ * <pre> {@code
+ * evaluateExpression(source, XPathEvaluationResult.class);
+ * }</pre>
+ * <p>
+ *
+ * @implSpec
+ * The default implementation in the XPath API is equivalent to:
+ * <pre> {@code
+ * (XPathEvaluationResult)evaluateExpression(source, XPathEvaluationResult.class);
+ * }</pre>
+ *
+ * Since the {@code evaluate} method does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY}
+ * type, the default implementation of this method will always throw an
+ * IllegalArgumentException. Any implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must therefore
+ * override this method.
+ *
+ * @param source The {@code InputSource} of the document to evaluate over.
+ *
+ * @return The result of evaluating the expression.
+ *
+ * @throws XPathExpressionException If the expression cannot be evaluated.
+ * @throws IllegalArgumentException If the implementation of this method
+ * does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type.
+ * @throws NullPointerException If {@code source} is {@code null}.
+ *
+ * @since 1.9
+ */
+ default XPathEvaluationResult<?> evaluateExpression(InputSource source)
+ throws XPathExpressionException
+ {
+ return evaluateExpression(source, XPathEvaluationResult.class);
+ }
}
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactory.java Mon Jan 26 12:17:59 2015 +0300
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactory.java Tue Jan 27 22:01:46 2015 -0800
@@ -117,7 +117,7 @@
* and returns it if it is successfully created.
* </li>
* <li>
- * ${java.home}/conf/jaxp.properties is read and the value associated with the key being the system property above is looked for.
+ * ${java.home}/lib/jaxp.properties is read and the value associated with the key being the system property above is looked for.
* If present, the value is processed just like above.
* </li>
* <li>
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactoryFinder.java Mon Jan 26 12:17:59 2015 +0300
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactoryFinder.java Tue Jan 27 22:01:46 2015 -0800
@@ -176,9 +176,9 @@
String javah = ss.getSystemProperty( "java.home" );
String configFile = javah + File.separator +
- "conf" + File.separator + "jaxp.properties";
+ "lib" + File.separator + "jaxp.properties";
- // try to read from $java.home/conf/jaxp.properties
+ // try to read from $java.home/lib/jaxp.properties
try {
if(firstTime){
synchronized(cacheProps){
@@ -193,7 +193,7 @@
}
}
final String factoryClassName = cacheProps.getProperty(propertyName);
- debugPrintln("found " + factoryClassName + " in $java.home/conf/jaxp.properties");
+ debugPrintln("found " + factoryClassName + " in $java.home/jaxp.properties");
if (factoryClassName != null) {
xpathFactory = createInstance(factoryClassName, true);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathNodes.java Tue Jan 27 22:01:46 2015 -0800
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.xml.xpath;
+
+import java.util.Iterator;
+import org.w3c.dom.Node;
+
+/**
+ * XPathNodes represents a set of nodes selected by a location path as specified
+ * in <a href="http://www.w3.org/TR/xpath/#node-sets">XML Path Language (XPath)
+ * Version 1.0, 3.3 Node-sets</a>.
+ *
+ * @since 1.9
+ */
+public interface XPathNodes extends Iterable<Node> {
+
+ /**
+ * Returns an iterator of the Nodes.
+ *
+ * @return an Iterator.
+ */
+ @Override
+ public abstract Iterator<Node> iterator();
+
+ /**
+ * Returns the number of items in the result
+ *
+ * @return The number of items in the result
+ */
+ public abstract int size();
+
+ /**
+ * Returns a Node at the specified position
+ *
+ * @param index Index of the element to return.
+ * @return The Node at the specified position.
+ * @throws javax.xml.xpath.XPathException If the index is out of range
+ * (index < 0 || index >= size())
+ */
+ public abstract Node get(int index)
+ throws XPathException;
+}
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/package.html Mon Jan 26 12:17:59 2015 +0300
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/package.html Tue Jan 27 22:01:46 2015 -0800
@@ -1,6 +1,8 @@
-<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
<!--
-Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
This code is free software; you can redistribute it and/or modify it
@@ -23,35 +25,35 @@
or visit www.oracle.com if you need additional information or have any
questions.
-->
+</head>
+<body bgcolor="white">
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>javax.xml.xpath</title>
-<meta name="@author" content="mailto:Ben@galbraiths.org" />
-<meta name="@author" content="mailto:Norman.Walsh@Sun.com" />
-<meta name="@author" content="mailto:Jeff.Suttor@Sun.com" />
-<meta name="@see" content="http://www.w3.org/TR/xpath" />
-<meta name="@since" content="1.5" />
-</head>
-
-<body>
-
-<p>This package provides an <em>object-model neutral</em> API for the
+This package provides an <em>object-model neutral</em> API for the
evaluation of XPath expressions and access to the evaluation
environment.
-</p>
-<p>The following XML standards apply:</p>
-
-<ul>
-<li><a href="http://www.w3.org/TR/xpath">XML Path Language (XPath) Version 1.0</a></li>
-</ul>
+<p>
+The XPath API supports <a href="http://www.w3.org/TR/xpath">
+ XML Path Language (XPath) Version 1.0</a>
<hr />
-<h2>XPath Overview</h2>
+<ul>
+ <li><a href='#XPath.Overview'>1. XPath Overview</a></li>
+ <li><a href='#XPath.Expressions'>2. XPath Expressions</a></li>
+ <li><a href='#XPath.Datatypes'>3. XPath Data Types</a>
+ <ul>
+ <li><a href='#XPath.Datatypes.QName'>3.1 QName Types</a>
+ <li><a href='#XPath.Datatypes.Class'>3.2 Class Types</a>
+ <li><a href='#XPath.Datatypes.Enum'>3.3 Enum Types</a>
+ </ul>
+ </li>
+ <li><a href='#XPath.Context'>4. XPath Context</a></li>
+ <li><a href='#XPath.Use'>5. Using the XPath API</a></li>
+</ul>
+<p>
+<a name="XPath.Overview"></a>
+<h3>1. XPath Overview</h3>
<p>The XPath language provides a simple, concise syntax for selecting
nodes from an XML document. XPath also provides rules for converting a
@@ -67,7 +69,8 @@
replace many lines of DOM API code.
</p>
-<h3>XPath Expressions</h3>
+<a name="XPath.Expressions"></a>
+<h3>2. XPath Expressions</h3>
<p>An XPath <em>expression</em> is composed of a <em>location
path</em> and one or more optional <em>predicates</em>. Expressions
@@ -76,18 +79,22 @@
<p>The following is an example of a simple XPath expression:</p>
+<blockquote>
<pre>
/foo/bar
</pre>
+</blockquote>
<p>This example would select the <code><bar></code> element in
an XML document such as the following:</p>
+<blockquote>
<pre>
<foo>
-<bar/>
+ <bar/>
</foo>
</pre>
+</blockquote>
<p>The expression <code>/foo/bar</code> is an example of a location
path. While XPath location paths resemble Unix-style file system
@@ -96,30 +103,36 @@
<code><bar></code> elements in the following document would be
selected by the <code>/foo/bar</code> expression:</p>
+<blockquote>
<pre>
<foo>
-<bar/>
-<bar/>
-<bar/>
+ <bar/>
+ <bar/>
+ <bar/>
</foo>
</pre>
+</blockquote>
<p>A special location path operator, <code>//</code>, selects nodes at
any depth in an XML document. The following example selects all
<code><bar></code> elements regardless of their location in a
document:</p>
+<blockquote>
<pre>
//bar
</pre>
+</blockquote>
<p>A wildcard operator, *, causes all element nodes to be selected.
The following example selects all children elements of a
-<code><foo></code> element:</p>
+<code><foo></code> element:
+<blockquote>
<pre>
/foo/*
</pre>
+</blockquote>
<p>In addition to element nodes, XPath location paths may also address
attribute nodes, text nodes, comment nodes, and processing instruction
@@ -166,35 +179,27 @@
<code><foo></code> elements that contain an <code>include</code>
attribute with the value of <code>true</code>:</p>
+<blockquote>
<pre>
//foo[@include='true']
</pre>
+</blockquote>
<p>Predicates may be appended to each other to further refine an
expression, such as:</p>
+<blockquote>
<pre>
//foo[@include='true'][@mode='bar']
</pre>
-
-<h3>Using the XPath API</h3>
-
-<p>
-The following example demonstrates using the XPath API to select one
-or more nodes from an XML document:</p>
+</blockquote>
-<pre>
-XPath xpath = XPathFactory.newInstance().newXPath();
-String expression = "/widgets/widget";
-InputSource inputSource = new InputSource("widgets.xml");
-NodeList nodes = (NodeList) xpath.evaluate(expression, inputSource, XPathConstants.NODESET);
-</pre>
-
-<h3>XPath Expressions and Types</h3>
+<a name="XPath.Datatypes"></a>
+<h3>3. XPath Data Types</h3>
<p>While XPath expressions select nodes in the XML document, the XPath
API allows the selected nodes to be coalesced into one of the
-following other data types:</p>
+following data types:</p>
<ul>
<li><code>Boolean</code></li>
@@ -202,14 +207,10 @@
<li><code>String</code></li>
</ul>
-<p>The desired return type is specified by a {@link
-javax.xml.namespace.QName} parameter in method call used to evaluate
-the expression, which is either a call to
-<code>XPathExpression.evalute(...)</code> or to one of the
-<code>XPath.evaluate(...)</code> convenience methods. The allowed
-QName values are specified as constants in the {@link
-javax.xml.xpath.XPathConstants} class; they are:</p>
-
+<a name="XPath.Datatypes.QName"></a>
+<h3>3.1 QName types</h3>
+The XPath API defines the following {@link javax.xml.namespace.QName} types to
+represent return types of an XPath evaluation:
<ul>
<li>{@link javax.xml.xpath.XPathConstants#NODESET}</li>
<li>{@link javax.xml.xpath.XPathConstants#NODE}</li>
@@ -218,26 +219,71 @@
<li>{@link javax.xml.xpath.XPathConstants#NUMBER}</li>
</ul>
+<p>The return type is specified by a {@link javax.xml.namespace.QName} parameter
+in method call used to evaluate the expression, which is either a call to
+<code>XPathExpression.evalute(...)</code> or <code>XPath.evaluate(...)</code>
+methods.
+
<p>When a <code>Boolean</code> return type is requested,
<code>Boolean.TRUE</code> is returned if one or more nodes were
-selected; otherwise, <code>Boolean.FALSE</code> is returned.</p>
+selected; otherwise, <code>Boolean.FALSE</code> is returned.
<p>The <code>String</code> return type is a convenience for retrieving
the character data from a text node, attribute node, comment node, or
processing-instruction node. When used on an element node, the value
of the child text nodes is returned.
-</p>
<p>The <code>Number</code> return type attempts to coalesce the text
of a node to a <code>double</code> data type.
-</p>
+
+<a name="XPath.Datatypes.Class"></a>
+<h3>3.2 Class types</h3>
+In addition to the QName types, the XPath API supports the use of Class types
+through the <code>XPathExpression.evaluteExpression(...)</code> or
+<code>XPath.evaluateExpression(...)</code> methods.
-<h3>XPath Context</h3>
+The XPath data types are mapped to Class types as follows:
+<ul>
+<li><code>Boolean</code> -- <code>Boolean.class</code></li>
+<li><code>Number</code> -- <code>Number.class</code></li>
+<li><code>String</code> -- <code>String.class</code></li>
+<li><code>Nodeset</code> -- <code>XPathNodes.class</code></li>
+<li><code>Node</code> -- <code>Node.class</code></li>
+</ul>
+
+<p>
+Of the subtypes of Number, only Double, Integer and Long are supported.
+
+<a name="XPath.Datatypes.Enum"></a>
+<h3>3.3 Enum types</h3>
+Enum types are defined in {@link javax.xml.xpath.XPathEvaluationResult.XPathResultType}
+that provide mappings between the QName and Class types above. The result of
+evaluating an expression using the <code>XPathExpression.evaluteExpression(...)</code>
+or <code>XPath.evaluateExpression(...)</code> methods will be of one of these types.
+
+<a name="XPath.Context"></a>
+<h3>4. XPath Context</h3>
<p>XPath location paths may be relative to a particular node in the
-document, known as the <code>context</code>. Consider the following
-XML document:</p>
+document, known as the <code>context</code>. A context consists of:
+<ul>
+ <li>a node (the context node)</li>
+ <li>a pair of non-zero positive integers (the context position and the context size)</li>
+ <li>a set of variable bindings</li>
+ <li>a function library</li>
+ <li>the set of namespace declarations in scope for the expression</li>
+</ul>
+<p>
+It is an XML document tree represented as a hierarchy of nodes, a
+{@link org.w3c.dom.Node} for example, in the JDK implementation.
+
+<a name="XPath.Use"></a>
+<h3>5. Using the XPath API</h3>
+
+Consider the following XML document:
+<p>
+<blockquote>
<pre>
<widgets>
<widget>
@@ -246,36 +292,88 @@
</widget>
</widgets>
</pre>
+</blockquote>
-<p>The <code><widget></code> element can be selected with the
-following XPath API code:</p>
+<p>
+The <code><widget></code> element can be selected with the following process:
+<blockquote>
<pre>
// parse the XML as a W3C Document
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = builder.parse(new File("/widgets.xml"));
+//Get an XPath object and evaluate the expression
XPath xpath = XPathFactory.newInstance().newXPath();
String expression = "/widgets/widget";
Node widgetNode = (Node) xpath.evaluate(expression, document, XPathConstants.NODE);
+
+//or using the evaluateExpression method
+Node widgetNode = xpath.evaluateExpression(expression, document, Node.class);
</pre>
+</blockquote>
<p>With a reference to the <code><widget></code> element, a
-relative XPath expression can now written to select the
+relative XPath expression can be written to select the
<code><manufacturer></code> child element:</p>
+<blockquote>
<pre>
XPath xpath = XPathFactory.newInstance().newXPath();
<strong>String expression = "manufacturer";</strong>
Node manufacturerNode = (Node) xpath.evaluate(expression, <strong>widgetNode</strong>, XPathConstants.NODE);
+
+//or using the evaluateExpression method
+Node manufacturerNode = xpath.evaluateExpression(expression, <strong>widgetNode</strong>, Node.class);
</pre>
+</blockquote>
+
+<p>
+In the above example, the XML file is read into a DOM Document before being passed
+to the XPath API. The following code demonstrates the use of InputSource to
+leave it to the XPath implementation to process it:
+
+<blockquote>
+<pre>
+XPath xpath = XPathFactory.newInstance().newXPath();
+String expression = "/widgets/widget";
+InputSource inputSource = new InputSource("widgets.xml");
+NodeList nodes = (NodeList) xpath.evaluate(expression, inputSource, XPathConstants.NODESET);
+
+//or using the evaluateExpression method
+XPathNodes nodes = xpath.evaluate(expression, inputSource, XPathNodes.class);
+</pre>
+</blockquote>
-<ul>
-<li>Author <a href="mailto:Ben@galbraiths.org">Ben Galbraith</a></li>
-<li>Author <a href="mailto:Norman.Walsh@Sun.com">Norman Walsh</a></li>
-<li>Author <a href="mailto:Jeff.Suttor@Sun.com">Jeff Suttor</a></li>
-<li>See <a href="http://www.w3.org/TR/xpath">XML Path Language (XPath) Version 1.0</a></li>
-<li>Since 1.5</li>
-</ul>
+<p>
+In the above cases, the type of the expected results are known. In case where
+the result type is unknown or any type, the {@link javax.xml.xpath.XPathEvaluationResult}
+may be used to determine the return type. The following code demonstrates the usage:
+<blockquote>
+<pre>
+XPathEvaluationResult<?> result = xpath.evaluateExpression(expression, document);
+switch (result.type()) {
+ case NODESET:
+ XPathNodes nodes = (XPathNodes)result.value();
+ ...
+ break;
+}
+</pre>
+</blockquote>
+
+<p>
+The XPath 1.0 Number data type is defined as a double. However, the XPath
+specification also provides functions that returns Integer type. To facilitate
+such operations, the XPath API allows Integer and Long to be used in
+{@code evaluateExpression} method such as the following code:
+<p>
+<blockquote>
+<pre>
+int count = xpath.evaluate("count(/widgets/widget)", document, Integer.class);
+</pre>
+</blockquote>
+
+@since 1.5
+
</body>
</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/xpath/XPathAnyTypeTest.java Tue Jan 27 22:01:46 2015 -0800
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package javax.xml.xpath;
+
+import java.io.File;
+import javax.xml.xpath.*;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/*
+ * @bug 8054196
+ * @summary Test for the project XPath: support any type. This test covers the new
+ * evaluateExpression methods of XPath, as well as XPathNodes and XPathEvaluationResult.
+ */
+public class XPathAnyTypeTest extends XPathTestBase {
+ /*
+ Test for resolveFunction(QName functionName,int arity); evaluate throws
+ NPE if functionName is null.
+ */
+
+ @Test(dataProvider = "xpath", expectedExceptions = NullPointerException.class)
+ public void testCheckXPathFunctionResolver02(XPath xpath) throws XPathExpressionException {
+ xpath.setXPathFunctionResolver((functionName, arity) -> null);
+ assertEquals(xpath.evaluate(null, "5"), "2");
+ }
+ /*
+ Check that NPE is thrown when expression is null.
+ */
+
+ @Test(dataProvider = "xpath", expectedExceptions = NullPointerException.class)
+ public void test01(XPath xpath) throws XPathExpressionException {
+ double result = xpath.evaluateExpression(null, (Object) null, Double.class);
+ }
+
+ /*
+ Check that NPE is thrown when the class type is null.
+ */
+ @Test(dataProvider = "xpath", expectedExceptions = NullPointerException.class)
+ public void test02(XPath xpath) throws XPathExpressionException {
+ double result = xpath.evaluateExpression("1+1", (Object) null, null);
+ }
+
+ /*
+ Parameter item can be null when the expression does not depends on the
+ context.
+ */
+ @Test(dataProvider = "xpath")
+ public void test03(XPath xpath) throws XPathExpressionException {
+ int result = xpath.evaluateExpression("1+1", (Object) null, Integer.class);
+ assertTrue(result == 2);
+ }
+
+ /*
+ * Test return type: boolean.
+ */
+ @Test(dataProvider = "document")
+ public void test04(XPath xpath, Document doc) throws XPathExpressionException {
+ boolean result1 = xpath.evaluateExpression("boolean(/Customers/Customer[@id=3])", doc, Boolean.class);
+ assertTrue(result1);
+ }
+
+ /*
+ * Test return type: numeric. Subtypes supported: Double, Integer and Long
+ */
+ @Test(dataProvider = "document")
+ public void test05(XPath xpath, Document doc) throws XPathExpressionException {
+ double result1 = xpath.evaluateExpression("count(/Customers/Customer)", doc, Double.class);
+ assertTrue(result1 == 3.0);
+ int result2 = xpath.evaluateExpression("count(/Customers/Customer)", doc, Integer.class);
+ assertTrue(result2 == 3);
+ long result3 = xpath.evaluateExpression("count(/Customers/Customer)", doc, Long.class);
+ assertTrue(result3 == 3);
+ }
+
+ /*
+ * Test return type: numeric. Of the subtypes of Number, only Double,
+ * Integer and Long are required.
+ */
+ @Test(dataProvider = "invalidNumericTypes", expectedExceptions = IllegalArgumentException.class)
+ public void test06(XPath xpath, Class<Number> type) throws XPathExpressionException {
+ xpath.evaluateExpression("1+1", (Object) null, type);
+ }
+
+ /*
+ * Test return type: String.
+ */
+ @Test(dataProvider = "document")
+ public void test07(XPath xpath, Document doc) throws XPathExpressionException {
+ String result1 = xpath.evaluateExpression("string(/Customers/Customer[@id=3]/Phone/text())", doc, String.class);
+ assertTrue(result1.equals("3333333333"));
+ }
+
+ /*
+ * Test return type: NodeSet.
+ */
+ @Test(dataProvider = "document")
+ public void test08(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathNodes nodes = xpath.evaluateExpression("/Customers/Customer", doc, XPathNodes.class);
+ assertTrue(nodes.size() == 3);
+ for (Node n : nodes) {
+ assertEquals(n.getLocalName(), "Customer");
+ }
+ }
+
+ /*
+ * Test return type: Node.
+ */
+ @Test(dataProvider = "document")
+ public void test09(XPath xpath, Document doc) throws XPathExpressionException {
+ Node n = xpath.evaluateExpression("/Customers/Customer[@id=3]", doc, Node.class);
+ assertEquals(n.getLocalName(), "Customer");
+ }
+
+ /*
+ * Test return type: Unsupported type.
+ */
+ @Test(dataProvider = "document", expectedExceptions = IllegalArgumentException.class)
+ public void test10(XPath xpath, Document doc) throws XPathExpressionException {
+ File n = xpath.evaluateExpression("/Customers/Customer[@id=3]", doc, File.class);
+ }
+
+ /*
+ * Test return type: Any::Boolean.
+ */
+ @Test(dataProvider = "document")
+ public void test11(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathEvaluationResult<?> result = xpath.evaluateExpression("boolean(/Customers/Customer[@id=3])", doc);
+ verifyResult(result, true);
+ }
+
+ /*
+ * Test return type: Any::Number.
+ */
+ @Test(dataProvider = "document")
+ public void test12(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathEvaluationResult<?> result = xpath.evaluateExpression("count(/Customers/Customer)", doc);
+ verifyResult(result, 3.0);
+ }
+
+ /*
+ * Test return type: Any::String.
+ */
+ @Test(dataProvider = "document")
+ public void test13(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathEvaluationResult<?> result = xpath.evaluateExpression(
+ "string(/Customers/Customer[@id=3]/Phone/text())", doc, XPathEvaluationResult.class);
+ verifyResult(result, "3333333333");
+ }
+
+ /*
+ * Test return type: Any::Nodeset.
+ */
+ @Test(dataProvider = "document")
+ public void test14(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathEvaluationResult<?> result = xpath.evaluateExpression("/Customers/Customer", doc);
+ verifyResult(result, "Customer");
+ }
+
+ /*
+ * Test return type: Any::Node.
+ */
+ @Test(dataProvider = "document")
+ public void test15(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathEvaluationResult<?> result = xpath.evaluateExpression("/Customers/Customer[@id=3]", doc);
+ verifyResult(result, "Customer");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/xpath/XPathExpAnyTypeTest.java Tue Jan 27 22:01:46 2015 -0800
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.xml.xpath;
+
+import java.io.File;
+import javax.xml.xpath.*;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/*
+ * @bug 8054196
+ * @summary Test for the project XPath: support any type. This test covers the new
+ * evaluateExpression methods of XPathExpression.
+ */
+public class XPathExpAnyTypeTest extends XPathTestBase {
+
+ /*
+ * Check that NPE is thrown when the class type is null.
+ */
+ @Test(dataProvider = "xpath", expectedExceptions = NullPointerException.class)
+ public void test02(XPath xpath) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("1+1");
+ double result = exp.evaluateExpression((Object)null, null);
+ }
+
+ /*
+ * Parameter item can be null when the expression does not depends on the
+ * context.
+ */
+ @Test(dataProvider = "xpath")
+ public void test03(XPath xpath) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("1+1");
+ int result = exp.evaluateExpression((Object)null, Integer.class);
+ assertTrue(result == 2);
+ }
+
+ /*
+ * Test return type: boolean.
+ */
+ @Test(dataProvider = "document")
+ public void test04(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("boolean(/Customers/Customer[@id=3])");
+ boolean result1 = exp.evaluateExpression(doc, Boolean.class);
+ assertTrue(result1);
+ }
+
+ /*
+ * Test return type: numeric.
+ */
+ @Test(dataProvider = "document")
+ public void test05(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("count(/Customers/Customer)");
+ double result1 = exp.evaluateExpression(doc, Double.class);
+ assertTrue(result1 == 3.0);
+
+ int result2 = exp.evaluateExpression(doc, Integer.class);
+ assertTrue(result2 == 3);
+ }
+
+ /*
+ * Test return type: String.
+ */
+ @Test(dataProvider = "document")
+ public void test06(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("string(/Customers/Customer[@id=3]/Phone/text())");
+ String result1 = exp.evaluateExpression(doc, String.class);
+ assertTrue(result1.equals("3333333333"));
+ }
+
+ /*
+ * Test return type: NodeSet.
+ */
+ @Test(dataProvider = "document")
+ public void test07(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("/Customers/Customer");
+ XPathNodes nodes = exp.evaluateExpression(doc, XPathNodes.class);
+ assertTrue(nodes.size() == 3);
+ for (Node n : nodes) {
+ assertEquals(n.getLocalName(), "Customer");
+ }
+ }
+
+ /*
+ * Test return type: Node.
+ */
+ @Test(dataProvider = "document")
+ public void test08(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("/Customers/Customer[@id=3]");
+ Node n = exp.evaluateExpression(doc, Node.class);
+ assertEquals(n.getLocalName(), "Customer");
+ }
+
+ /*
+ * Test return type: Unsupported type.
+ */
+ @Test(dataProvider = "document", expectedExceptions = IllegalArgumentException.class)
+ public void test09(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("/Customers/Customer[@id=3]");
+ File n = exp.evaluateExpression(doc, File.class);
+ }
+
+ /*
+ * Test return type: Any::Boolean.
+ */
+ @Test(dataProvider = "document")
+ public void test10(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("boolean(/Customers/Customer[@id=3])");
+ XPathEvaluationResult<?> result = exp.evaluateExpression(doc);
+ verifyResult(result, true);
+ }
+
+ /*
+ * Test return type: Any::Number.
+ */
+ @Test(dataProvider = "document")
+ public void test11(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("count(/Customers/Customer)");
+ XPathEvaluationResult<?> result = exp.evaluateExpression(doc);
+ verifyResult(result, 3.0);
+ }
+
+ /*
+ * Test return type: Any::String.
+ */
+ @Test(dataProvider = "document")
+ public void test12(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("string(/Customers/Customer[@id=3]/Phone/text())");
+ XPathEvaluationResult<?> result = exp.evaluateExpression(doc, XPathEvaluationResult.class);
+ verifyResult(result, "3333333333");
+ }
+
+ /*
+ * Test return type: Any::Nodeset.
+ */
+ @Test(dataProvider = "document")
+ public void test13(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("/Customers/Customer");
+ XPathEvaluationResult<?> result = exp.evaluateExpression(doc);
+ verifyResult(result, "Customer");
+ }
+
+ /*
+ * Test return type: Any::Node.
+ */
+ @Test(dataProvider = "document")
+ public void test14(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("/Customers/Customer[@id=3]");
+ XPathEvaluationResult<?> result = exp.evaluateExpression(doc);
+ verifyResult(result, "Customer");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/xpath/XPathTestBase.java Tue Jan 27 22:01:46 2015 -0800
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package javax.xml.xpath;
+
+import java.io.ByteArrayInputStream;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.xml.parsers.DocumentBuilderFactory;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import org.testng.annotations.DataProvider;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/*
+ * Base class for XPath test
+ */
+class XPathTestBase {
+
+ static final String rawXML
+ = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+ + "<Customers>"
+ + " <Customer id=\"1\">"
+ + " <Name>name1</Name>"
+ + " <Phone>1111111111</Phone>"
+ + " <Email>123@xyz.com</Email>"
+ + " <Address>"
+ + " <Street>1111 111st ave</Street>"
+ + " <City>The City</City>"
+ + " <State>The State</State>"
+ + " </Address>"
+ + " </Customer>"
+ + " <Customer id=\"2\">"
+ + " <Name>name1</Name>"
+ + " <Phone>2222222222</Phone>"
+ + " <Email>123@xyz.com</Email>"
+ + " <Address>"
+ + " <Street>2222 222nd ave</Street>"
+ + " <City>The City</City>"
+ + " <State>The State</State>"
+ + " </Address>"
+ + " </Customer>"
+ + " <Customer id=\"3\">"
+ + " <Name>name1</Name>"
+ + " <Phone>3333333333</Phone>"
+ + " <Email>123@xyz.com</Email>"
+ + " <Address>"
+ + " <Street>3333 333rd ave</Street>"
+ + " <City>The City</City>"
+ + " <State>The State</State>"
+ + " </Address>"
+ + " </Customer>"
+ + "</Customers>";
+
+ void verifyResult(XPathEvaluationResult<?> result, Object expected) {
+ switch (result.type()) {
+ case BOOLEAN:
+ assertTrue(((Boolean) result.value()).equals(expected));
+ return;
+ case NUMBER:
+ assertTrue(((Double) result.value()).equals(expected));
+ return;
+ case STRING:
+ assertTrue(((String) result.value()).equals(expected));
+ return;
+ case NODESET:
+ XPathNodes nodes = (XPathNodes) result.value();
+ for (Node n : nodes) {
+ assertEquals(n.getLocalName(), expected);
+ }
+ return;
+ case NODE:
+ assertTrue(((Node) result.value()).getLocalName().equals(expected));
+ return;
+ }
+ assertFalse(true, "Unsupported type");
+ }
+
+ /*
+ * DataProvider: XPath object
+ */
+ @DataProvider(name = "xpath")
+ Object[][] getXPath() {
+ return new Object[][]{{XPathFactory.newInstance().newXPath()}};
+ }
+
+ /*
+ * DataProvider: Numeric types not supported
+ */
+ @DataProvider(name = "invalidNumericTypes")
+ Object[][] getInvalidNumericTypes() {
+ XPath xpath = XPathFactory.newInstance().newXPath();
+ return new Object[][]{{xpath, AtomicInteger.class},
+ {xpath, AtomicInteger.class},
+ {xpath, AtomicLong.class},
+ {xpath, BigDecimal.class},
+ {xpath, BigInteger.class},
+ {xpath, Byte.class},
+ {xpath, Float.class},
+ {xpath, Short.class}
+ };
+ }
+
+ /*
+ * DataProvider: XPath and Document objects
+ */
+ @DataProvider(name = "document")
+ Object[][] getDocument() throws Exception {
+ DocumentBuilderFactory dBF = DocumentBuilderFactory.newInstance();
+ dBF.setValidating(false);
+ dBF.setNamespaceAware(true);
+ Document doc = dBF.newDocumentBuilder().parse(
+ new ByteArrayInputStream(rawXML.getBytes("UTF-8")));
+
+ return new Object[][]{{XPathFactory.newInstance().newXPath(), doc}};
+ }
+}