自定义Java 5 的新XPath API 函数
Java 5 的XPath API已经非常好用了,它实现了XPath1.0标准,功能已经比较强大了。
但是,还可以对它进行扩展,自定义XPath API 函数。例如,想要支持matches函数,以便匹配正则表达式,就可如下:
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
xpath.setXPathFunctionResolver(new MatchesFunctionContext());
xpath.setNamespaceContext(new MyNamespaceContext());
XPathExpression expr = xpath.compile("//*[ext:matches(@href,\"/photos/.*/[0-9]+/\")]/IMG");Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes;nodes = (NodeList) result;// XPathAPI.selectNodeList(doc, "//*[@id=\"Main\"]");
System.out.println(nodes.getLength());
for (int i = 0; i < nodes.getLength(); i++) {
// System.out.println(nodes.item(i).getNodeName());
// System.out.println(nodes.item(i).getTextContent());
}
import javax.xml.namespace.QName;
import javax.xml.xpath.XPathFunction;
import javax.xml.xpath.XPathFunctionResolver;public class MatchesFunctionContext implements XPathFunctionResolver{
private static final QName name
= new QName("http://ext.com", "matches");public XPathFunction resolveFunction(QName name, int arity) {
if (name.equals(MatchesFunctionContext.name) ) {
return new FuncMatches();
}
return null;
}}
import java.util.Iterator;
import javax.xml.namespace.NamespaceContext;
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;
}}
import java.util.List;import javax.xml.xpath.XPathFunction;
import javax.xml.xpath.XPathFunctionException;import org.w3c.dom.Node;
import org.w3c.dom.NodeList;/**
* Execute the Contains() function.
*
* @xsl.usage advanced
*/
public class FuncMatches implements XPathFunction {
static final long serialVersionUID = 5084753781887919723L;/**
*
*/
public Object evaluate(List args) throws XPathFunctionException {if (args.size() != 2) {
throw new XPathFunctionException(
"Wrong number of arguments to valid-isbn()");
}
Object o = args.get(0);
String s1 = null;
if (o instanceof NodeList) {NodeList list = (NodeList) o;
if (list.getLength() == 0) {
return Boolean.FALSE;
}Node node = list.item(0);
// getTextContent is available in Java 5 and DOM 3.
// In Java 1.4 and DOM 2, you'd need to recursively
// accumulate the content.
s1 = node.getTextContent();
}String s2 = (String) args.get(1);
// Add this check for JDK consistency for empty strings.
if (s1.length() == 0 && s2.length() == 0)
return Boolean.TRUE;boolean match = s1.matches(s2);
return (match) ? Boolean.TRUE : Boolean.FALSE;
}}