2012-05-23 35 views
7

tôi muốn làm một truy vấn XPath trong hồ sơ này (đoạn trích được hiển thị):Java XPath: Các câu hỏi với xmlns namespace mặc định

<?xml version="1.0" encoding="UTF-8"?> 
<!-- MetaDataAPI generated on: Friday, May 25, 2007 3:26:31 PM CEST --> 
<ModelClass xmlns="http://xml.sap.com/2002/10/metamodel/webdynpro" xmlns:IDX="urn:sap.com:WebDynpro.ModelClass:2.0"> 
    <ModelClass.Parent> 
     <Core.Reference package="com.test.mypackage" name="ModelName" type="Model"/> 

Đây là một đoạn mã Tôi đang sử dụng:

DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); 
DocumentBuilder builder = domFactory.newDocumentBuilder(); 
Document document = builder.parse(new File(testFile)); 
XPathFactory factory = XPathFactory.newInstance(); 
XPath xpath = factory.newXPath(); 
xpath.setNamespaceContext(new NamespaceContext() { 
    public String getNamespaceURI(String prefix) { 
... 

String result = xpath.evaluate(xpathQueryString, document); 
System.out.println(result); 

Vấn đề tôi gặp phải là khi không gian tên mặc định được tham chiếu trong truy vấn XPath, phương thức getNamespaceURI không được gọi để giải quyết nó. Truy vấn này ví dụ như không trích xuất bất cứ điều gì:

//xmlns:ModelClass.Parent/xmlns:Core.Reference[@type=\"Model\"]/@package

Bây giờ tôi đã cố gắng "lừa" phân tích cú pháp bằng cách thay thế xmlns với một tiền tố giả d và sau đó viết phương pháp getNamespaceURI phù hợp (như vậy để trở http://xml.sap.com/2002/10/metamodel/webdynpro khi gặp phải d). Trong trường hợp này, getNamespaceURI được gọi nhưng kết quả của việc đánh giá biểu thức XPath luôn luôn là một chuỗi rỗng.

Nếu tôi loại bỏ các không gian tên khỏi tệp và từ biểu thức truy vấn XPath, tôi có thể nhận được chuỗi tôi muốn (com.test.mypackage).

Có cách nào để mọi thứ hoạt động bình thường với không gian tên mặc định không?

Trả lời

8

Trong Namespace ngữ cảnh của bạn, ràng buộc một tiền tố của sự lựa chọn của bạn (ví dụ df) đến namespace URI trong tài liệu

xpath.setNamespaceContext(new NamespaceContext() { 
    public String getNamespaceURI(String prefix) { 
     switch (prefix) { 
     case "df": return "http://xml.sap.com/2002/10/metamodel/webdynpro"; 
     ... 
     } 
    }); 

và sau đó sử dụng tiền tố đó trong biểu thức đường dẫn của bạn để đủ điều kiện tên phần tử ví dụ /df:ModelClass/df:ModelClass.Parent/df:Core.Reference[@type = 'Model']/@package.

+0

Hi Martin, tôi đã thử nó nhưng nó không hoạt động ... –

+4

Đảm bảo bạn cũng tạo không gian tên nhận biết DocumentBuilder http://docs.oracle.com/javase/6/docs/api/javax/ xml/parsers/DocumentBuilderFactory.html # setNamespaceAware% 28boolean% 29 trước khi làm việc với các không gian tên. –

+0

Điều đó đã làm được điều đó. Tôi nghĩ rằng DocumentBuilder được mặc định biết về các không gian tên. Cám ơn bạn một lần nữa. –

10

Đặc tả XPath 1.0 yêu cầu "không có tiền tố nghĩa là không có vùng tên". Vì vậy, JAXP, được thiết kế cho XPath 1.0, hoàn toàn đúng để ngăn bạn gắn kết "tiền tố rỗng" với một số không gian tên không null.

XPath 2.0 cho phép bạn khai báo một không gian tên mặc định cho các tên không đủ tiêu chuẩn trong biểu thức XPath của bạn, nhưng để tận dụng, bạn sẽ cần một API (chẳng hạn như s9api của Saxon) để tận dụng tính năng này.

+0

Cảm ơn bạn Michael về thông tin bổ sung. –