| <?xml version="1.0" standalone="no"?> |
| <!DOCTYPE s1 SYSTEM "../../style/dtd/document.dtd"> |
| <!-- |
| * 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 |
| * |
| * 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, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| --> |
| |
| <s1 title="Using the JAXP XPath APIs"> |
| <ul> |
| <li><link anchor="basic">Basic steps</link></li> |
| <li><link anchor="plugin">Plugging in the XPathFactory</link></li> |
| <li><link anchor="namespacecontext">Using NamespaceContext</link></li> |
| <li><link anchor="variableresolver">Using XPathVariableResolver</link></li> |
| <li><link anchor="functionresolver">Using XPathFunctionResolver</link></li> |
| <li><link anchor="sampleresolver">Using the sample XPathFunctionResolver</link></li> |
| </ul> |
| |
| <anchor name="basic"/> |
| <s2 title="Basic steps"> |
| <ol> |
| <li><link anchor="xpathfactory">Instantiate an XPathFactory</link></li> |
| <li><link anchor="xpath">Create an XPath</link></li> |
| <li><link anchor="xpathexpression">(optional) Create an XPathExpression</link></li> |
| <li><link anchor="evaluation">Evaluate the XPath expression in a specified context</link></li> |
| </ol> |
| <p>The following example illustrates the basic steps involved in evaluating an XPath expression.</p> |
| <source>// 1. Instantiate an XPathFactory. |
| javax.xml.xpath.XPathFactory factory = |
| javax.xml.xpath.XPathFactory.newInstance(); |
| |
| // 2. Use the XPathFactory to create a new XPath object |
| javax.xml.xpath.XPath xpath = factory.newXPath(); |
| |
| // 3. Compile an XPath string into an XPathExpression |
| javax.xml.xpath.XPathExpression expression = xpath.compile("/doc/name"); |
| |
| // 4. Evaluate the XPath expression on an input document |
| String result = expression.evaluate(new org.xml.sax.InputSource("foo.xml")); |
| </source> |
| </s2> |
| |
| <anchor name="xpathfactory"/> |
| <s2 title="1. Instantiate an XPathFactory"> |
| <p><jump href="apidocs/javax/xml/xpath/XPathFactory.html">XPathFactory</jump> is an abstract class with two static |
| newInstance() methods (<jump href="apidocs/javax/xml/xpath/XPathFactory.html#newInstance()">newInstance()</jump> and |
| <jump href="apidocs/javax/xml/xpath/XPathFactory.html#newInstance(java.lang.String)">newInstance(String uri)</jump>) |
| that instantiate the concrete subclass designated as the javax.xml.xpath.XPathFactory service provider. |
| The optional parameter uri specifies the object model. The implementation in &xslt4j2; only supports the |
| W3C DOM object model, identified by the URI <jump href="apidocs/javax/xml/xpath/XPathFactory.html#DEFAULT_OBJECT_MODEL_URI"> |
| DEFAULT_OBJECT_MODEL_URI</jump>.</p> |
| |
| <p>The default service provider for the javax.xml.xpath.XPathFactory service is |
| <jump href="apidocs/org/apache/xpath/jaxp/XPathFactoryImpl.html">org.apache.xpath.jaxp.XPathFactoryImpl</jump>. |
| </p> |
| </s2> |
| |
| <anchor name="xpath"/> |
| <s2 title="2. Create an XPath"> |
| You can use the <jump href="apidocs/javax/xml/xpath/XPathFactory.html#newXPath()">XPathFactory.newXPath()</jump> |
| method to create a new <jump href="apidocs/javax/xml/xpath/XPath.html">XPath</jump>. |
| </s2> |
| |
| <anchor name="xpathexpression"/> |
| <s2 title="3. (optional) Create an XPathExpression"> |
| You can use the <jump href="apidocs/javax/xml/xpath/XPath.html#compile(java.lang.String)">XPath.compile(String expression)</jump> |
| method to compile an XPath string into an <jump href="apidocs/javax/xml/xpath/XPathExpression.html">XPathExpression</jump> object |
| for later evaluation. This is an optional step. |
| You can evaluate an XPath expression without compiling it first. |
| </s2> |
| |
| <anchor name="evaluation"/> |
| <s2 title="4. Evaluate an XPath expression"> |
| <p>If you compile an XPath String into an <jump href="apidocs/javax/xml/xpath/XPathExpression.html">XPathExpression</jump> |
| in step 3, you can use one of the four evaluate() methods in |
| the XPathExpression interface to evaluate the XPath expression. If the evaluation context is a W3C Node in an |
| existing Document, you can use the <jump href="apidocs/javax/xml/xpath/XPathExpression.html#evaluate(java.lang.Object)"> |
| evaluate(Object item)</jump> or <jump href="apidocs/javax/xml/xpath/XPathExpression.html#evaluate(java.lang.Object, javax.xml.namespace.QName)"> |
| evaluate(Object item, QName returnType)</jump> method by passing the context item as the first parameter. |
| The method with a returnType parameter allows you to specify the return type as one of the following supported |
| return types: |
| <li><jump href="apidocs/javax/xml/xpath/XPathConstants.html#BOOLEAN">XPathConstants.BOOLEAN</jump></li> |
| <li><jump href="apidocs/javax/xml/xpath/XPathConstants.html#NUMBER">XPathConstants.NUMBER</jump></li> |
| <li><jump href="apidocs/javax/xml/xpath/XPathConstants.html#STRING">XPathConstants.STRING</jump></li> |
| <li><jump href="apidocs/javax/xml/xpath/XPathConstants.html#NODESET">XPathConstants.NODESET</jump></li> |
| <li><jump href="apidocs/javax/xml/xpath/XPathConstants.html#NODE">XPathConstants.NODE</jump></li> |
| </p> |
| <p>If the returnType parameter is not specified, the default is XPathConstants.STRING.</p> |
| <p>If the evaluation context is an input document, you can use one of the two evaluate() methods with an |
| InputSource parameter (<jump href="apidocs/javax/xml/xpath/XPathExpression.html#evaluate(org.xml.sax.InputSource)">evaluate(InputSource source)</jump> |
| or <jump href="apidocs/javax/xml/xpath/XPathExpression.html#evaluate(org.xml.sax.InputSource, javax.xml.namespace.QName)"> |
| evaluate(InputSource source, QName returnType)</jump>) to evaluate the XPath expression.</p> |
| <p>The compiling step allows you to reuse an XPath expression for evaluation on multiple contexts. |
| If an XPath expression is only used once, you can use one of the four evaluate() methods in the |
| <jump href="apidocs/javax/xml/xpath/XPath.html">XPath</jump> interface |
| to evaluate the XPath expression without compiling it first.</p> |
| </s2> |
| |
| <anchor name="plugin"/> |
| <s2 title="Plugging in the XPathFactory"> |
| <p>The Java API for XML Processing interfaces enable you to plug in your own implementation of XPathFactory. |
| The abstract class XPathFactory has a static newInstance() method that instantiates a concrete Factory |
| which wraps the underlying implementation. The newInstance() method uses system property settings to determine |
| which implementation to instantiate.</p> |
| <p>&xslt4j2; is distributed with a pre-configured setting for the provider of the XPathFactory service. This setting is in |
| xalan.jar in META-INF/services/javax.xml.xpath.XPathFactory, with a value of org.apache.xpath.jaxp.XPathFactoryImpl.</p> |
| <p>You can plug in a new XPathFactory as follows (in order of precedence): |
| <ol> |
| <li>Set the system property "javax.xml.xpath.XPathFactory" + ":uri" from the command line when you |
| launch Java or from within your application, where uri is the URI of the underlying object model. The URI of |
| the default W3C DOM object model is <code>http://java.sun.com/jaxp/xpath/dom</code>.</li> |
| <li>Set the property in jaxp.properties in the JAVA_HOME/lib directory, where JAVA_HOME is the root of |
| the JDK.</li> |
| <li>Revise the entry in src/META-INF/services/javax.xml.xpath.XPathFactory and rebuild xalan.jar. Each potential service |
| provider entry in this file is required to implement the method <code>isObjectModelSupported(String objectModel).</code> |
| The first service provider found in class loader order that supports the specified object model will be used.</li> |
| </ol> |
| </p> |
| </s2> |
| |
| <anchor name="namespacecontext"/> |
| <s2 title="Using NamespaceContext"> |
| <p>If namespace prefixes are used in an XPath expression, the XPath processor needs to know what namespace URIs |
| the prefixes are bound to. Logically a prefix can only be bound to a single Namespace URI in the current scope. However, |
| a Namespace URI can be bound to multiple prefixes in the current scope. The information about namespace |
| prefix to URI mappings is provided by an object that implements the |
| <jump href="apidocs/javax/xml/namespace/NamespaceContext.html">javax.xml.namespace.NamespaceContext</jump> interface.</p> |
| <p>Suppose you want to evaluate the XPath expression <code>"/foo:document/bar:element"</code> on the following xml document:</p> |
| <source> |
| <?xml version='1.0'?> |
| <foo:document xmlns:foo="http://apache.org/foo" xmlns:bar="http://apache.org/bar"> |
| <bar:element>MyBar</bar:element> |
| </foo:document> |
| </source> |
| |
| <p>You need to create your own implementation of <jump href="apidocs/javax/xml/namespace/NamespaceContext.html">NamespaceContext</jump> |
| to inform the XPath processor what namespace URIs |
| the prefixes are bound to. For the example above, you can create a NamespaceContext implementation as follows:</p> |
| <source> |
| public class MyNamespaceContext implements NamespaceContext |
| { |
| public String getNamespaceURI(String prefix) |
| { |
| if (prefix.equals("foo")) |
| return "http://apache.org/foo"; |
| else if (prefix.equals("bar")) |
| return "http://apache.org/bar"; |
| else |
| return XMLConstants.NULL_NS_URI; |
| } |
| |
| public String getPrefix(String namespace) |
| { |
| if (namespace.equals("http://apache.org/foo")) |
| return "foo"; |
| else if (namespace.equals("http://apache.org/bar")) |
| return "bar"; |
| else |
| return null; |
| } |
| |
| public Iterator getPrefixes(String namespace) |
| { |
| return null; |
| } |
| } |
| </source> |
| |
| <p>Then you can use the <jump href="apidocs/javax/xml/xpath/XPath.html#setNamespaceContext(javax.xml.namespace.NamespaceContext)"> |
| XPath.setNamespaceContext(NamespaceContext nsContext)</jump> |
| method to set the NamespaceContext on the XPath object you create using the <link anchor="basic">basic steps</link>.</p> |
| <p>The XPath processor in &xslt4j2; only uses the <jump href="apidocs/javax/xml/namespace/NamespaceContext.html#getNamespaceURI(java.lang.String)"> |
| getNamespaceURI(String prefix)</jump> |
| method on NamespaceContext. The other two methods |
| <jump href="apidocs/javax/xml/namespace/NamespaceContext.html#getPrefix(java.lang.String)">getPrefix(String namespace)</jump> |
| and <jump href="apidocs/javax/xml/namespace/NamespaceContext.html#getPrefixes(java.lang.String)">getPrefixes(String namespace)</jump> |
| are not used. If the NamespaceContext object is only used by the XPath processor, you can let the unused methods |
| return null for simplicity.</p> |
| |
| </s2> |
| |
| <anchor name="variableresolver"/> |
| <s2 title="Using XPathVariableResolver"> |
| <p><jump href="apidocs/javax/xml/xpath/XPathVariableResolver.html">XPathVariableResolver</jump> provides access to the set of user |
| defined XPath variables. If an XPath expression contains |
| a variable reference, we need to set a XPathVariableResolver on the XPath object using the |
| <jump href="apidocs/javax/xml/xpath/XPath.html#setXPathVariableResolver(javax.xml.xpath.XPathVariableResolver)"> |
| XPath.setXPathVariableResolver(XPathVariableResolver resolver)</jump> |
| method. You can also set the XPathVariableResolver on the XPathFactory, using the |
| <jump href="apidocs/javax/xml/xpath/XPathFactory.html#setXPathVariableResolver(javax.xml.xpath.XPathVariableResolver)"> |
| XPathFactory.setXPathVariableResolver(XPathVariableResolver resolver)</jump> |
| method. If the XPathVariableResolver is set on the XPathFacory, then all XPath objects constructed from this |
| XPathFactory will use the specified XPathVariableResolver by default. The XPath processor uses the |
| XPathVariableResolver to retrieve the value of a user defined variable. In the course of evaluating any |
| single XPath expression, a variable's value must be immutable. </p> |
| <p>Suppose that the XPath expression to be evaluated is <code>"$x + $y"</code>, we need to provide a XPathVariableResolver |
| implementation from which the values of the variable x and y can be retrieved. For this example, the |
| XPathVariableResolver implementation can be written as follows:</p> |
| <source> |
| public class MyVariableResolver implements XPathVariableResolver |
| { |
| public Object resolveVariable(QName var) |
| { |
| if (var == null) |
| throw new NullPointerException("The variable name cannot be null"); |
| |
| if (var.equals(new QName("x"))) |
| return new Integer(2); |
| else if (var.equals(new QName("y"))) |
| return new Integer(3); |
| else |
| return null; |
| } |
| } |
| </source> |
| </s2> |
| |
| <anchor name="functionresolver"/> |
| <s2 title="Using XPathFunctionResolver"> |
| <p><jump href="apidocs/javax/xml/xpath/XPathFunctionResolver.html">XPathFunctionResolver</jump> provides access to the |
| set of user defined XPathFunctions. If an XPath expression contains |
| an extension function, you can use the |
| <jump href="apidocs/javax/xml/xpath/XPath.html#setXPathFunctionResolver(javax.xml.xpath.XPathFunctionResolver)"> |
| XPath.setXPathFunctionResolver(XPathFunctionResolver resolver)</jump> |
| method to set a XPathFunctionResolver on the XPath object. You can also use the |
| <jump href="apidocs/javax/xml/xpath/XPathFactory.html#setXPathFunctionResolver(javax.xml.xpath.XPathFunctionResolver)"> |
| XPathFactory.setXPathFunctionResolver(XPathFunctionResolver resolver)</jump> |
| method to set a XPathFunctionResolver on the XPathFactory, in which case all XPath objects constructed from this |
| XPathFactory will use the specified XPathVariableResolver by default.</p> |
| <p>The XPathFunctionResolver interface only has one method:</p> |
| <p><jump href="apidocs/javax/xml/xpath/XPathFunctionResolver.html#resolveFunction(javax.xml.namespace.QName, int)"> |
| <code>public XPathFunction resolveFunction(QName functionName, int arity)</code></jump></p> |
| <p>This method returns a XPathFunction object from the given function name and arity. XPath functions are resolved |
| by name and arity. The parameter types have no impact here. XPathFunctionResolver is only used for functions with |
| an explicit prefix. It is not needed for XPath built-in functions and it cannot be used to override those functions.</p> |
| <p>The XPathFunction interface has only one method:</p> |
| <p><jump href="apidocs/javax/xml/xpath/XPathFunction.html#evaluate(java.util.List)"> |
| <code>public java.lang.Object evaluate(java.util.List args) throws XPathFunctionException</code></jump></p> |
| <p>The function parameters are passed in using the args parameter as a java.util.List. And the method returns the result |
| of evaluating the XPath function as an Object.</p> |
| <p>To support the use of extension functions in an XPath expression, a user needs to provide implementations of |
| the XPathFunctionResolver and XPathFunction interfaces. The resolveFunction method of the XPathFunctionResolver |
| implementation should return an object of a class that implements the XPathFunction interface.</p> |
| <p>Suppose we want to evaluate the XPath expression <code>"ext:myAdditionFunction(2, 3)"</code>, and the purpose |
| of the extension function is simply to return the sum of the two parameters. Because an extension function |
| always has an explicit prefix, we also need to implement the NamespaceContext interface to provide a namespace |
| prefix to URI mapping. For this example, we need to implement three interfaces: NamespaceContext, |
| XPathFunctionResolver and XPathFunction. A sample implementation is as follows:</p> |
| <source> |
| public class MyNamespaceContext implements NamespaceContext |
| { |
| public String getNamespaceURI(String prefix) |
| { |
| if (prefix == null) |
| throw new IllegalArgumentException("The prefix cannot be null."); |
| |
| if (prefix.equals("ext")) |
| return "http://ext.com"; |
| else |
| return null; |
| } |
| |
| public String getPrefix(String namespace) |
| { |
| if (namespace == null) |
| throw new IllegalArgumentException("The namespace uri cannot be null."); |
| if (namespace.equals("http://ext.com")) |
| return "ext"; |
| else |
| return null; |
| } |
| |
| public Iterator getPrefixes(String namespace) |
| { |
| return null; |
| } |
| } |
| |
| /** |
| * The XPathFunctionResolver implementation is used to evaluate |
| * the extension function "ext:myAdditionFunction(2, 3)". |
| */ |
| public class MyFunctionResolver implements XPathFunctionResolver |
| { |
| /** |
| * This method returns a customized XPathFunction implementation |
| * for the extension function "ext:myAdditionFunction(2, 3)". |
| */ |
| public XPathFunction resolveFunction(QName fname, int arity) |
| { |
| if (fname == null) |
| throw new NullPointerException("The function name cannot be null."); |
| |
| // We only recognize one function, i.e. ex:addFunc(). |
| if (fname.equals(new QName("http://ext.com", "myAdditionFunction", "ext"))) |
| /** |
| * Return a customized implementation of XPathFunction. We need |
| * to implement the evaluate(List) method. |
| */ |
| return new XPathFunction() { |
| /** |
| * The actual implementation of the extension function. |
| * Just cast two arguments to Double and add them together. |
| */ |
| public Object evaluate(java.util.List args) { |
| if (args.size() == 2) { |
| Double arg1 = (Double)args.get(0); |
| Double arg2 = (Double)args.get(1); |
| return new Double(arg1.doubleValue() + arg2.doubleValue()); |
| } |
| else |
| return null; |
| } |
| }; |
| else |
| return null; |
| } |
| } |
| </source> |
| </s2> |
| |
| <anchor name="sampleresolver"/> |
| <s2 title="Using the sample XPathFunctionResolver"> |
| <p>Normally you need to provide your own implementation of XPathFunctionResolver in order to use |
| extension functions in XPath expressions. In &xslt4j2;, we provide a sample implementation |
| of XPathFunctionResolver in the class org.apache.xalan.extensions.XPathFunctionResolverImpl, with supports |
| for Java and EXSLT extensions. If you set the XPathFunctionResolver to an object of this class, then |
| you can use Java and EXSLT extension functions in the XPath expression. You also need to use a |
| NamespaceContext along with the sample XPathFunctionResolver. &xslt4j2; also includes a sample |
| implementation of NamespaceContext in org.apache.xalan.extensions.ExtensionNamespaceContext, which |
| provides the following namespace prefix to URI mappings:</p> |
| |
| <table> |
| <tr> |
| <th>Prefix</th> |
| <th>URI</th> |
| </tr> |
| <tr> |
| <td>java</td> |
| <td>http://xml.apache.org/xalan/java</td> |
| </tr> |
| <tr> |
| <td>exslt</td> |
| <td>http://exslt.org/common</td> |
| </tr> |
| <tr> |
| <td>math</td> |
| <td>http://exslt.org/math</td> |
| </tr> |
| <tr> |
| <td>set</td> |
| <td>http://exslt.org/sets</td> |
| </tr> |
| <tr> |
| <td>str</td> |
| <td>http://exslt.org/strings</td> |
| </tr> |
| <tr> |
| <td>dyn</td> |
| <td>http://exslt.org/dynamic</td> |
| </tr> |
| <tr> |
| <td>datetime</td> |
| <td>http://exslt.org/dates-and-times</td> |
| </tr> |
| </table> |
| |
| <p>Suppose you want to evaluate the XPath expression <code>"math:max(/doc/num)"</code>, which contains |
| an EXSLT extension call. Here the prefix <code>"math"</code> corresponds to the URI <code>"http://exslt.org/math"</code>. |
| The following code snippet demonstrates how to use the sample XPathFunctionResolver to evaluate the |
| XPath expression above:</p> |
| <source> |
| XPathFactory factory = XPathFactory.newInstance(); |
| XPath xpath = factory.newXPath(); |
| |
| // set the NamespaceContext to |
| // org.apache.xalan.extensions.ExtensionNamespaceContext |
| xpath.setNamespaceContext(new org.apache.xalan.extensions.ExtensionNamespaceContext()); |
| |
| // set the XPathFunctionResolver to |
| // org.apache.xalan.extensions.XPathFunctionResolverImpl |
| xpath.setXPathFunctionResolver(new org.apache.xalan.extensions.XPathFunctionResolverImpl()); |
| |
| // Evaluate the XPath expression "math:max(/doc/num)" against |
| // the input document numlist.xml |
| Object result = xpath.evaluate("math:max(/doc/num)", new InputSource("numlist.xml"), XPathConstants.NUMBER); |
| </source> |
| </s2> |
| </s1> |