你其實可以同時使用:
public static String escape(String s) {
Matcher matcher = Pattern.compile("['\"]")
.matcher(s);
StringBuilder buffer = new StringBuilder("concat(");
int start = 0;
while (matcher.find()) {
buffer.append("'")
.append(s.substring(start, matcher.start()))
.append("',");
buffer.append("'".equals(matcher.group()) ? "\"'\"," : "'\"',");
start = matcher.end();
}
if (start == 0) {
return "'" + s + "'";
}
return buffer.append("'")
.append(s.substring(start))
.append("'")
.append(")")
.toString();
}
這可使用此代碼來證明XPath中的自定義函數和變量 - 但是對於許多用途來說,快速入侵可能會更有效率。
下面是一些代碼,我開發爲我們的學生學習的工具。它可以讓你這樣做:
// create some variable we want to use in the xpath
xPathVariableAndFunctionResolver.newVariable("myNamespace", "id", "xs:string", "l2"); // myNamespace is declared in the namespace context with prefix 'my'
// create an XPath expression
String expression = "//did:Component[@id=$my:id]"; // variable $namespace:name
XPathExpression findComponents = xPathFunctionAndVariableOperator.compile(expression);
// execute the XPath expression against the document
NodeList statements = (NodeList)findComponents.evaluate(document, XPathConstants.NODESET);
和XPath函數一樣。該代碼,第一個爲正常的XPath evalutation包裝:
public class XPathOperator {
protected XPath xPath;
protected XPathFactory xPathFactory;
private Hashtable<String, XPathExpression> compiled = new Hashtable<String, XPathExpression>();
protected void initFactory() throws XPathFactoryConfigurationException {
xPathFactory = XPathFactory.newInstance(XPathConstants.DOM_OBJECT_MODEL);
}
protected void initXPath(NamespaceContext context) {
xPath = xPathFactory.newXPath();
xPath.setNamespaceContext(context);
}
public XPathOperator(NamespaceContext context) throws XPathFactoryConfigurationException {
initFactory();
initXPath(context);
}
public Object evaluate(Document document, String expression, QName value) throws XPathExpressionException {
// create an XPath expression - http://www.zvon.org/xxl/XPathTutorial/General/examples.html
XPathExpression findStatements = compile(expression);
// execute the XPath expression against the document
return (NodeList)findStatements.evaluate(document, value);
}
public XPathExpression compile(String expression) throws XPathExpressionException {
if(compiled.containsKey(expression)) {
return (XPathExpression) compiled.get(expression);
}
XPathExpression xpath = xPath.compile(expression);
System.out.println("Compiled XPath " + expression);
compiled.put(expression, xpath);
return xpath;
}
}
然後我們使用命名空間的增加,當然自定義變量和函數的概念,:
public class XPathFunctionAndVariableOperator extends XPathOperator {
public XPathFunctionAndVariableOperator(NamespaceContext context, XPathVariableResolver xPathVariableResolver, XPathFunctionResolver xPathFunctionResolver) throws XPathFactoryConfigurationException {
super(context);
xPath.setXPathVariableResolver(xPathVariableResolver);
xPath.setXPathFunctionResolver(xPathFunctionResolver);
}
}
這不會有太大的樂趣沒有變量和函數解析器:
public class XPathVariableAndFunctionResolver implements XPathVariableResolver, XPathFunctionResolver {
private Hashtable functions = new Hashtable();
private Hashtable variables = new Hashtable();
private SchemaDVFactory factory = SchemaDVFactory.getInstance();
public XPathFunction resolveFunction(QName functionName, int arity) {
Hashtable table = (Hashtable)functions.get(functionName.getNamespaceURI());
if(table != null) {
XPathFunction function = (XPathFunction)table.get(functionName.getLocalPart());
if(function == null) {
throw new RuntimeException("Function " + functionName.getLocalPart() + " does not exist in namespace " + functionName.getNamespaceURI() + "!");
}
System.out.println("Resolved function " + functionName + " with " + arity + " argument(s)");
return function;
}
throw new RuntimeException("Function namespace " + functionName.getNamespaceURI() + " does not exist!");
}
/**
*
* Adds a variable using namespace and name, primitive type and default value
*
* @param namespace
* @param name
* @param datatype one of the built-in XML datatypes
* @param value
* @throws InvalidDatatypeValueException if value is not of correct datatype
*/
@SuppressWarnings("unchecked")
public void newVariable(String namespace, String name, String datatype, String value) throws InvalidDatatypeValueException {
int index = datatype.indexOf(":");
if(index != -1) {
datatype = datatype.substring(index+1);
}
XSSimpleType builtInType = factory.getBuiltInType(datatype);
if(builtInType == null) {
throw new RuntimeException("Null type for " + datatype);
}
ValidationState validationState = new ValidationState();
ValidatedInfo validatedInfo = new ValidatedInfo();
builtInType.validate(value, validationState, validatedInfo);
System.out.println("Defined variable " + name + " as " + datatype + " with value " + value);
Hashtable table;
if(!variables.containsKey(namespace)) {
table = new Hashtable();
variables.put(namespace, table);
} else {
table = (Hashtable)variables.get(namespace);
}
table.put(name, new Object[]{validatedInfo, builtInType});
}
public void newVariableValue(String namespace, String name, String value) throws InvalidDatatypeValueException {
ValidationState validationState = new ValidationState();
Hashtable table;
if(!variables.containsKey(namespace)) {
throw new RuntimeException("Unknown variable namespace " + namespace);
} else {
table = (Hashtable)variables.get(namespace);
}
Object[] bundle = (Object[])table.get(name);
ValidatedInfo validatedInfo = (ValidatedInfo)bundle[0];
XSSimpleType builtInType = (XSSimpleType)bundle[1];
builtInType.validate(value, validationState, validatedInfo); // direct reference transfer of value
System.out.println("Assigned value " + validatedInfo.normalizedValue + " to variable " + name);
}
public Object resolveVariable(QName variableName) {
Hashtable table;
if(!variables.containsKey(variableName.getNamespaceURI())) {
throw new RuntimeException("Unknown variable namespace " + variableName.getNamespaceURI());
} else {
table = (Hashtable)variables.get(variableName.getNamespaceURI());
}
Object[] bundle = (Object[])table.get(variableName.getLocalPart());
if(bundle != null) {
ValidatedInfo var = (ValidatedInfo)bundle[0];
if(var != null) {
switch(var.actualValueType) { // some types omitted, customize your own
case XSConstants.INTEGER_DT:
case XSConstants.DECIMAL_DT:
case XSConstants.INT_DT:
case XSConstants.LONG_DT:
case XSConstants.SHORT_DT:
case XSConstants.BYTE_DT:
case XSConstants.UNSIGNEDBYTE_DT:
case XSConstants.UNSIGNEDINT_DT:
case XSConstants.UNSIGNEDLONG_DT:
case XSConstants.UNSIGNEDSHORT_DT:
return new Integer(var.normalizedValue);
case XSConstants.DATE_DT:
case XSConstants.DATETIME_DT:
case XSConstants.GDAY_DT:
case XSConstants.GMONTH_DT:
case XSConstants.GMONTHDAY_DT:
case XSConstants.GYEAR_DT:
case XSConstants.GYEARMONTH_DT:
case XSConstants.DURATION_DT:
case XSConstants.TIME_DT:
return new Date(var.normalizedValue);
case XSConstants.FLOAT_DT:
return new Float(Float.parseFloat(var.normalizedValue));
case XSConstants.DOUBLE_DT:
return new Double(Double.parseDouble(var.normalizedValue));
case XSConstants.STRING_DT:
case XSConstants.QNAME_DT:
return var.normalizedValue;
default:
throw new RuntimeException("Unknown datatype " + var.actualValueType + " for variable " + variableName + " in namespace " + variableName.getNamespaceURI());
}
}
}
throw new RuntimeException("Could not resolve value " + variableName + " in namespace " + variableName.getNamespaceURI());
}
public void addFunction(String namespace, String name, XPathFunction function) {
Hashtable table;
if(!functions.containsKey(namespace)) {
table = new Hashtable();
functions.put(namespace, table);
} else {
table = (Hashtable)functions.get(namespace);
}
table.put(name, function);
}
}
的功能顯然不能被包含在上述範圍內,因爲通常運行自定義代碼(即整個的一點是,你寫你的O WN類),這樣的東西去像
public abstract class XPathFunctionImpl implements XPathFunction {
/**
* This function is called by the XPath expression as it implements the interface XPathFunction
*/
protected int numberArguments;
public Object evaluate(List args) throws XPathFunctionException {
if(args.size() == numberArguments) {
return evaluateImpl(args);
}
throw new RuntimeException("Illegal number of arguments for " + this);
}
public abstract Object evaluateImpl(List args) throws XPathFunctionException;
}
然後在工具/子類evaluateImpl(你自己的邏輯。)不知何故。
這肯定使字符串追加顯得相當...吸引力;)注:此代碼是幾年前的,有可能存在這樣做的所有一個更好的辦法。
你爲什麼不能建立XPath表達式動態,我的意思是像 「//書[作者= '」 + AUTHORNAME + 「'] /標題/文本()」? – 2011-04-14 12:37:45
是那是一個好的開始。我也試試。謝謝。 – JavaBits 2011-04-14 12:48:08
如何將變量註冊到XPath評估上下文完全取決於XPath引擎API。 – 2011-04-14 16:04:05