2011-07-19 60 views
5

Có thể bằng công cụ biểu thức JAX-P xpath cổ phần hoặc một công cụ tương thích khác để biên dịch biểu thức xpath cho phép tham số hóa không?Có thể tham số hóa một biểu thức Java XPath đã biên dịch được không?

Tôi đang tìm xem liệu có API nào cho phép nhà phát triển đặt trình giữ chỗ trong xpath được biên dịch và thay thế các giá trị đó tại thời gian chạy hay không.

Bất kỳ thông tin chi tiết nào về điều này là có hay không và nếu có cảnh báo, cạm bẫy hoặc chỉ đơn giản là "không làm điều đó", lời khuyên loại sẽ được đánh giá cao.

(Lưu ý rằng tôi đã chỉnh sửa "băng qua luồng" ... đang trò chuyện với đồng nghiệp liên quan đến xpath & cụm từ thông dụng ... chỉ xảy ra khi bị trói buộc về tinh thần ... xin lỗi vì sự nhầm lẫn)

+0

Thật tuyệt vời! Cảm ơn bạn đã trả lời câu hỏi này. Tôi đã hoàn toàn bỏ qua API về điều này, cảm ơn tất cả vì đã chỉ ra điều này! –

Trả lời

4

Tôi không hoàn toàn chắc chắn nơi "cụm từ thông dụng" phù hợp với câu hỏi của bạn.

API JAXP cho phép biểu thức XPath chứa biến (ví dụ: //emp[ssn=$e]) và giá trị của các biến được lấy tại thời gian chạy bằng cách gọi hàm VariableResolver mà bạn cung cấp như một phần của API. Thông số JAXP khá lỏng lẻo về loại giá trị nào có thể chấp nhận được và điều này có thể thay đổi từ việc triển khai này sang thực hiện khác.

API XPath Saxon (s9api) thực hiện điều này và cho phép bạn khai báo rõ ràng các biến và loại của chúng tại thời điểm biểu thức được biên dịch và sau đó cung cấp giá trị cho các biến (của bất kỳ loại XPath 2.0 nào) khi biểu thức được thực hiện.

+0

bạn có thể cho chúng tôi một số mẫu mã, bạn của tôi không? – everton

+0

@Michael - xin lỗi về sự nhầm lẫn, tôi đã sửa câu hỏi của tôi xóa "thường xuyên" từ trên cao. Ngoài ra, bạn có thể cung cấp một mẫu mã nhỏ với câu trả lời của mình hoặc liên kết đến một trang thể hiện điều này không? Tôi đang xem xét API để kiểm tra nó. –

1

AFAIK, không. Tôi đã nghiên cứu một thời gian trước và kết thúc bằng cách sử dụng String.format().

Nhưng, theo cách này, bạn sẽ không thể biên dịch nó một lần như là một thông số xpath thông dụng, và đó là những gì tôi nghĩ bạn muốn (và những gì tôi muốn).

+0

vâng khá nhiều những gì tôi đã cố gắng ... oh well. –

7

Dưới đây là một thực hiện rất đơn giản của javax.xml.xpath.XPathVariableResolver

import java.util.HashMap; 
import java.util.Map; 
import javax.xml.namespace.QName; 
import javax.xml.xpath.XPathVariableResolver; 

public class SimpleVariableResolver implements XPathVariableResolver { 

    private static final Map<QName, Object> vars = 
     new HashMap<QName, Object>(); 

    public void addVariable(QName name, Object value) { 
     vars.put(name, value); 
    } 

    public Object resolveVariable(QName name) { 
     return vars.get(name); 
    } 

} 

Sử dụng nó như thế này:

public static void main(String[] args) throws ParserConfigurationException, 
     SAXException, IOException, XPathExpressionException { 

    DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); 
    DocumentBuilder builder = domFactory.newDocumentBuilder(); 
    Document doc = builder.parse("workbook.xml"); 

    XPath xpath = XPathFactory.newInstance().newXPath(); 
    SimpleVariableResolver resolver = new SimpleVariableResolver(); 
    resolver.addVariable(new QName(null, "id"), 2); 
    xpath.setXPathVariableResolver(resolver); 
    XPathExpression expr = xpath.compile("/root/element[@id=$id]"); 
    Object result = expr.evaluate(doc, XPathConstants.NODESET); 

    NodeList nodes = (NodeList) result; 
    for (int i = 0; i < nodes.getLength(); i++) { 
     System.out.println(nodes.item(i).getTextContent()); 
    } 
} 

Mở tài liệu này:

<root> 
    <element id="1">one</element> 
    <element id="2">two</element> 
    <element id="3">three</element> 
</root> 

Output:

two 
+0

Cảm ơn bạn đã đăng bài này! Tôi đã thực hiện điều này khá nhiều theo cùng một cách sau khi đọc API. –

+0

Tôi thích câu trả lời của @ everton-agner và đã bình chọn nó. Câu trả lời này cho thấy một ví dụ mã tuyệt vời, nhưng tôi nghĩ rằng các subtleties là 1) 'xpath.compile' phải được gọi cho mỗi biến thay thế, sau khi' xpath.setXPathVariableResolver' và 2) 'XPathVariableResolver' đề cập rằng các giá trị mỗi cá thể trả về phải không thay đổi. Vì vậy, với câu hỏi của OP, tôi không nghĩ rằng điều này là tương đương với SQL 'PreparedStatement' ràng buộc loại. – javabrett

Các vấn đề liên quan