java
  • xml
  • xpath
  • 2011-04-14 71 views 3 likes 
    3

    裏面我有books.xml文件,其中包含作者名和書名。我用下面的代碼來查詢books.xml如何使用Java字符串變量的XPath查詢

    XPathFactory factory = XPathFactory.newInstance(); 
    XPath xpath = factory.newXPath(); 
    XPathExpression expr 
        = xpath.compile("//book[author= 'Larry Niven']/title/text()"); 
    

    現在,而不是直接把名稱查詢,如果我想通過它在程序運行作爲一個字符串變量如何做到這一點的同時。只是把字符串變量名稱不工作!

    +0

    你爲什麼不能建立XPath表達式動態,我的意思是像 「//書[作者= '」 + AUTHORNAME + 「'] /標題/文本()」? – 2011-04-14 12:37:45

    +0

    是那是一個好的開始。我也試試。謝謝。 – JavaBits 2011-04-14 12:48:08

    +0

    如何將變量註冊到XPath評估上下文完全取決於XPath引擎API。 – 2011-04-14 16:04:05

    回答

    -2
    String rawXPath = "//book[author= '" + larrysName + "']/title/text()"; 
    

    String rawXPath = String.format("//book[author= '%s']/title/text()", larrysName); 
    

    其中larrysName是類型String從某處來的變量。

    +0

    謝謝你完美的作品。 – JavaBits 2011-04-14 12:45:49

    +2

    -1不幸的是,這對於像_O'Hara_或任何其他包含引號的文本這樣的名字來說並不完美。 – McDowell 2011-04-14 13:28:33

    +1

    @McDowell:好點。 – khachik 2011-04-14 13:36:13

    0

    如果你想有一個現成的實現,你可以使用支持的變量聲明公共JXPathhttp://commons.apache.org/jxpath/users-guide.html#Variables

    6

    這裏的問題是,當你有一個像筆者臭名昭著拉里「狼牙棒」 O'Niven

    在這種情況下,你需要躲避變量,在這個天真的實現:

    String xml = 
        "<xml><foo bar=\"Larry &quot;Basher&quot; O'Niven\">Ringworm</foo></xml>"; 
    String query = 
        String.format("//foo[@bar=%s]", escape("Larry \"Basher\" O'Niven")); 
    System.out.println(query); 
    String book = XPathFactory.newInstance() 
        .newXPath() 
        .evaluate(query, new InputSource(new StringReader(xml))); 
    System.out.println(query + " > " + book); 
    
    +0

    非常感謝您的幫助 – JavaBits 2011-04-14 19:19:41

    4

    你其實可以同時使用:

    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(你自己的邏輯。)不知何故。

    這肯定使字符串追加顯得相當...吸引力;)注:此代碼是幾年前的,有可能存在這樣做的所有一個更好的辦法。

    相關問題