1. Trang chủ
  2. » Công Nghệ Thông Tin

Các hàm API XPath của Java Thực hiện truy vấn XML từ các chương trình Java ppt

21 494 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 21
Dung lượng 213,85 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Các hàm API XPath của Java Thực hiện truy vấn XML từ các chương trình Java Elliotte Rusty Harold, Kỹ sư phần mềm, Polytechnic University Tóm tắt: Viết các biểu thức XPath dễ hơn rất nh

Trang 1

Các hàm API XPath của Java

Thực hiện truy vấn XML từ các chương trình Java

Elliotte Rusty Harold, Kỹ sư phần mềm, Polytechnic University

Tóm tắt:

Viết các biểu thức XPath dễ hơn rất nhiều nhiều so với việc viết mã chuyển hướng

Mô hình đối tượng tài liệu (Document Object Model - DOM) chi tiết Khi bạn cần rút trích thông tin từ tài liệu XML thì cách nhanh nhất và đơn giản nhất là nhúng biểu thức XPath vào bên trong chương trình Java™ Java 5 giới thiệu gói

java.xml.xpath, một thư viện độc lập mô hình đối tượng XML dùng để truy vấn các tài liệu XML với XPath

27/06/2007 - Từ các góp ý của người đọc, tác giả đã cập nhật các biểu thức XPath

đã được biên dịch (tham khảo phần mã ngắn ở Ví dụ 3)

25/08/2008 - Từ các góp ý của người đọc, tác giả đã thay

"http://www.example.org/books" thành "http://www.example.com/books" trong Ví

dụ 6, không gian tên (namespace) được đề cập đến trong đoạn văn trước Ví dụ 9,

và Ví dụ 9

Nếu bạn gửi một ai đó mua cho bạn một chai sữa thì bạn sẽ đề nghị như thế nào đến người đó để nhờ họ mua cho bạn? "Làm ơn mua hộ tôi một chai sữa" hay là nói "Đi ra ngoài thông qua cửa trước Rẽ trái ở phần vỉa hè dành cho người đi bộ

Đi bộ qua ba ngã tư Rẽ phải Đi bộ thêm một đoạn nữa Rẽ phải và đi vào cửa hàng Đi tới gian thứ tư Đi bộ khoảng năm mét rồi đi xuống gian dưới Rẽ trái Cầm lấy một hộp sữa Mang hộp sữa ra bàn thanh toán Thanh toán tiền cho chai sữa đó Và sau đó đi ngược lại đoạn đường vừa đi để đi về nhà bạn." Điều này thật

là nực cười Hầu hết đứa trẻ đều đủ thông minh để biết cách mang hộp sữa về nhà với một lời chỉ dẫn đơn giản "Làm ơn mua hộ tôi một chai sữa"

Các ngôn ngữ truy vấn và cơ chế tìm kiếm của máy tính cũng tương tự như nhau Việc "Tìm bản sao của Cryptonomicon" dễ dàng hơn là việc viết ra một cấu trúc logic chi tiết để tìm kiếm một số cơ sở dữ liệu Bởi vì các thao tác tìm kiếm có logic rất giống nhau nên bạn có thể đưa ra các ngôn ngữ tổng quát để có thể thực hiện câu lệnh như "Tìm tất cả các quyển sách của tác giả Neal Stephenson," và sau

đó viết một cơ chế xử lý các truy vấn đó dựa vào các kho dữ liệu nào đó

XPath

Trang 2

Trong rất nhiều ngôn ngữ truy vấn, Ngôn ngữ Truy vấn Có cấu trúc (SQL) là ngôn ngữ được thiết kế và cho phép thực hiện truy vấn trên các cơ sở dữ liệu quan hệ

Có một số ít các ngôn ngữ truy vấn bao gồm Ngôn ngữ truy vấn đối tượng (OOL)

và XQuery Tuy nhiên, chủ đề chính của bài viết này là về XPath cho nên ngôn ngữ truy vấn được thiết kế để thực hiện xử lý truy vấn trên các tài liệu XML Ví

dụ, một truy vấn XPath đơn giản là tìm ra các tiêu đề của tất cả các quyển sách trong tài liệu của tác giả Neal Stephenson, truy vấn phải trông có dạng như sau:

ArrayList result = new ArrayList();

NodeList books = doc.getElementsByTagName("book");

for (int i = 0; i < books.getLength(); i++) {

Element book = (Element) books.item(i);

NodeList authors = book.getElementsByTagName("author");

boolean stephenson = false;

for (int j = 0; j < authors.getLength(); j++) {

Element author = (Element) authors.item(j);

NodeList children = author.getChildNodes();

StringBuffer sb = new StringBuffer();

Trang 3

for (int k = 0; k < children.getLength(); k++) {

Node child = children.item(k);

// really should to do this recursively

if (child.getNodeType() == Node.TEXT_NODE) { sb.append(child.getNodeValue());

Trang 4

Điều này có thể tin hoặc không, đoạn mã DOM trong Ví dụ 1 thực sự không mang tính tổng quát và dõ dàng bằng các biểu thức XPath đơn giản Cái mà cho phép bạn có thể viết, sửa lỗi và bảo trì được tốt hơn? Tôi nghĩ câu trả lời đã rất rõ dàng

Có một điều phải nhớ rằng XPath không phải là ngôn ngữ Java trong thực tế, XPath không hoàn toàn là một ngôn ngữ lập trình Có nhiều vấn đề bạn không thể thấy được ở trong XPath, thậm chí kể cả các câu lệnh truy vấn cũng không thể được tạo ra trong XPath Ví dụ, XPath không không thể tìm thấy các quyển sách

đã đăng ký số quốc tế (ISBN) nếu kiểm tra không phù hợp các mã chữ số hay các tác giả của cuốn sách đó được lấy từ cơ sở dữ liệu tài khoản bên ngoài Thật may mắn, khi bạn tích hợp XPath vào trong chương trình Java thì bạn có thể tận dụng được ưu thể của cả hai ngôn ngữ này: Java sẽ giải quyết tốt những vấn đề liên quan đến Java, tương tự XPath sẽ giải quyết tốt những vấn đề liên quan tới XPath

Cho đến thời điểm gần đây, giao diện lập trình ứng dụng (API) được các chương trình Java sử dụng để tạo ra các câu truy vấn XPath khác nhau dựa trên cơ chế XPath Xalan có một API, Saxon có một loại khác và các cơ chế khác sẽ có các API khác Điều này có nghĩa rằng đoạn mã của bạn theo yêu cầu hướng vào một sản phẩm nào đó của bạn Theo một ý nào đó, bạn có thể làm thử nghiệm với các

cơ chế khác nhau để có được các đặc trưng cơ bản khác nhau mà không quá phức tạp hoặc không cần phải viết lại đoạn mã

Vì lý do này, Java 5 giới thiệu gói javax.xml.xpath cung cấp đầy đủ các cơ chế, ứng dụng và mô hình đối tượng độc lập thư viện XPath Gói này cũng có thể áp dụng được trong Java 1.3 và các phiên bản sau nếu bạn có cài đặt phần Java API for XML Processing (JAXP) 1.3 Nằm trong các sản phẩm khác, Xalan 2.7 và Saxon 8 bao gồm các thực thi của thư viện này

Một ví dụ đơn giản

Tôi sẽ bắt đầu bằng việc mô phỏng một cách chính xác các bước để thực hành trong phần này Sau đó tôi sẽ tập trung nghiên cứu vào một số vấn đề chi tiết cụ thể Giả sử bạn muốn truy vấn ra danh sách các quyển sách của tác giả Neal

Stephenson Trong trường hợp này, danh sách trong biểu mẫu được hiện thị như trong Ví dụ 2:

Trang 5

Ví dụ 2 Tài liệu XML chứa thông tin các quyển sách

Trang 6

Các nhà máy trừu tượng

XPathFactory là một nhà máy trừu tượng (abstract factory) Các mẫu thiết kế trừu tượng nhà máy này cho phép một API để hỗ trợ các mô hình đối tượng khác nhau như DOM, JDOM, và Xom Để chọn một mô hình khác, bạn truyền một URI xác định mô hình đối tượng tới phương thức XPathFactory.newInstance() Ví dụ, http://xom.nu/ có lẽ chọn XOM Tuy nhiên, trong thực tế, DOM là mô hình đối tượng duy nhất mà API này hỗ trợ đến giờ

Truy vấn XPath cho phép tìm ra tất cả các quyển sách một cách đơn giản:

//book[author="Neal Stephenson"] Để tìm tiêu đề của những cuốn sách này thì đơn giản chỉ làm thêm một bước và lúc đó biểu thức sẽ có dạng

//book[author="Neal Stephenson"]/title Cuối cùng, nếu bạn muốn truy vấn các nút con của phần tử title Bạn sẽ phải làm thêm một bước nữa để có một biểu thức đầy

đủ như sau //book[author="Neal Stephenson"]/title/text()

Bây giờ tôi sẽ đưa ra một chương trình đơn giản để thực hiện tìm kiếm này từ ngôn ngữ Java và sau đó in ra tiêu đề của tất cả các quyển sách tìm được Đầu tiên bạn cần phải tải được toàn bộ tài liệu vào đối tượng DOM Document Để đơn giản, tôi sẽ giả định rằng tài liệu được sử dụng là tệp books.xml nằm trong cùng

Trang 7

thư mục làm việc hiện thời Đây là một phân mã đơn giản để thực hiện phân tích tài liệu và tạo ra đối tượng Document tương ứng:

Ví dụ 3 Sự phân tích tài liệu bằng JAXP

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); // never forget this!

DocumentBuilder builder = factory.newDocumentBuilder();

Document doc = builder.parse("books.xml");

Đây là chuẩn JAXP và DOM, là chuẩn đã được trình bày và được nghiên cứu Tiếp theo bạn tạo ra XPathFactory:

XPathFactory factory =

XPathFactory.newInstance();

Sau đó bạn sử dụng factory để tạo ra đối tượng XPath:

XPath xpath = factory.newXPath();

Đối tượng XPath thực hiện biên dịch biểu thức XPath:

XPathExpression expr = xpath.compile("//book[author='Neal

Trang 8

Stephenson']/title/text()");

Đánh giá chung: Nếu bạn chỉ sử dụng biểu thức XPath một lần, bạn muốn bỏ qua

bước biên dịch và gọi phương thức evaluate() trên đối tượng XPath để thay thế Tuy nhiên, nếu bạn sử dụng lại biểu thức mẫu này thì trình biên dịch làm việc có

vẻ nhanh hơn

Cuối cùng, bạn thực hiện đánh giá biểu thức XPath để nhận được kết quả Khi biểu thức được đánh giá với mục đích đưa ra nội dung cụ thể của nút thì trong trường hợp này cần phải làm việc bên trong toàn bộ tài liệu Nó cũng cần thiết phải xác định kiểu trả lại:

Object result = expr.evaluate(doc,

XPathConstants.NODESET);

Sau đó bạn có thể gộp kết quả tới DOM NodeList và thực hiện lặp đi lặp lại để tìm

ra tất cả các tiêu đề:

NodeList nodes = (NodeList) result;

for (int i = 0; i < nodes.getLength(); i++) {

System.out.println(nodes.item(i).getNodeValue());

}

Ví dụ 4 đặt tất cả vào thành một chương trình đơn giản Chú ý rằng các phương thức này cũng có thể nắm bắt được một số ngoại lệ kiểm tra vì thế phải mô tả thêm mệnh đề throws:

Ví dụ 4 Một chương trình hoàn thiện để thực hiện truy vấn tài liệu XML với một biểu thức XPath xác định

Trang 9

public class XPathExample {

public static void main(String[] args)

throws ParserConfigurationException, SAXException,

XPathFactory factory = XPathFactory.newInstance();

XPath xpath = factory.newXPath();

XPathExpression expr

Trang 10

= xpath.compile("//book[author='Neal Stephenson']/title/text()");

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).getNodeValue());

}

}

}

Mô hình dữ liệu XPath

Khi bạn trộn hai ngôn ngữ khác nhau như XPath và Java, bạn cần chú ý tới các điểm nối của hai ngôn ngữ đó Tất nhiên không phải mọi điều phù hợp đều đúng Ngôn ngữ Java và XPath không phải là hai hệ thống giống hệt nhau XPath 1.0 chỉ

có bốn kiểu cơ bản sau:

 Tập hợp nút (node-set)

 Kiểu số (number)

 Kiểu logic (boolean)

 Kiểu chuỗi ký tự (string)

Trong ngôn ngữ Java có nhiều kiểu hơn bao gồm cả các kiểu đối tượng được định nghĩa bởi người sử dụng

Trang 11

Hầu hết các biểu thức XPath, đặc biệt là các đường dẫn, sẽ là các bộ nút Tuy nhiên, có thể có một số khả năng khác Ví dụ, Biểu thức count(//book) trả lại số các quyển sách có trong tài liệu Biểu thức XPath count(//book[@author="Neal Stephenson"]) > 10 trả lại một luận lý: đúng nếu có nhiều hơn 10 quyển sách của tác giả Neal Staphenson trong tài liệu ngược lại nếu có ít hơn 10 quyển sách trong tài liệu, sai nếu nếu có ít hơn 10

Phương thức evaluate() được mô tả trả lại Object Đối tượng gì được trả lại chính xác tùy thuộc vào kết quả trong biểu thức XPath và kiểu của đối tượng cũng tương ứng với kiểu các bạn đưa ra

 Kiểu số tương ứng với gói java.lang.Double

 Kiểu chuỗi ký tự tương ứng với gói java.lang.String

 Kiểu logic tương ứng với gói java.lang.Boolean

 Kiểu tập hợp nút tương ứng với gói org.w3c.dom.NodeList

XPath 2

Giả sử bạn đang làm việc với XPath 1.0 XPath 2 cho phép mở rộng và sử dụng lại kiểu hệ thống cơ bản Sự thay đổi chính trong Java XPath API cho phép hỗ trợ XPath 2 thêm vào một số kiểu dữ liệu mới của XPath

Khi bạn thực hiện đánh giá biểu thức XPath trong Java, tham biến thứ hai xác định kiểu trả lại mà bạn muốn Có năm khả năng có thể và tất cả các hằng số đều lưu nằm trong lớp javax.xml.xpath.XPathConstants:

Trang 12

XPathConstants.NODE, sau đó dùng phương thức evaluate() trả lại nút đầu tiên trong tài liệu cho phép Nếu biểu thức XPath lựa chọn một tập hợp rỗng và bạn sử dụng XPathConstants.NODE thì phương thức evaluate() trả lại giá trị rỗng

Nếu chuyển đổi theo yêu cầu không được thực hiện thì phương thức evaluate() bắt được ngoại lệ XPathException

Các ngữ cảnh không gian tên (Namespace contexts)

Nếu các phần tử trong tài liệu nằm trong một không gian tên thì biểu thức XPath cho truy vấn khi thực hiện thì phải sử dụng đúng không gian tên Biểu thức XPath không cần sử dụng các tiền tố giống nhau mà chỉ cần sử dụng các không gian tên URI giống nhau Vì vậy, khi tài liệu XML sử dụng không gian tên mặc định thì biểu thức XPath phải sử dụng tiền tố mặc dù mục tiêu tài liệu không sử dụng nó

Tuy nhiên, Chương trình Java không phải là một tài liệu XML nên giải pháp

không gian tên thông thường không áp dụng Thay vì bạn cung cấp đối tượng tương ứng với các dạng tiền tố tới các không gian tên URI Đối tượng này là ví dụ của giao diện javax.xml.namespace.NamespaceContext Ví dụ, giả sử tài liệu về các quyển sách được lưu trong không gian tên http://www.example.com/books có dạng như trong Ví dụ 5:

Ví dụ 5 Tài liệu XML sử dụng không gian tên mặc định

Trang 13

Ví dụ 6 Một ngữ cảnh đơn giản để thực hiện buộc một không gian tên cùng với giá trị mặc định

Trang 14

public String getNamespaceURI(String prefix) {

if (prefix == null) throw new NullPointerException("Null prefix");

else if ("pre".equals(prefix)) return "http://www.example.com/books";

else if ("xml".equals(prefix)) return XMLConstants.XML_NS_URI;

return XMLConstants.NULL_NS_URI;

}

// This method isn't necessary for XPath processing

public String getPrefix(String uri) {

throw new UnsupportedOperationException();

}

// This method isn't necessary for XPath processing either

public Iterator getPrefixes(String uri) {

throw new UnsupportedOperationException();

}

}

Thật không khó để sử dụng một ánh xạ để thực hiện lưu trữ các thông tin đã được gắn vào và thêm vào các phương thức khởi tạo để cho phép sử dụng dụng lại nhiều hơn ngữ cảnh không gian tên

Trang 15

Sau khi bạn tạo ra đối tượng NamespaceContext thay vì vậy cài đặt trên đối tượng XPath trước khi thực hiện biên dịch biểu thức Từ thời điểm này trở đi bạn có có thể thực hiện truy vấn bằng cách sử dụng những dạng tiền tố này phía trước Ví dụ:

Ví dụ 7 Truy vấn XPath sử dụng các không gian tên

XPathFactory factory = XPathFactory.newInstance();

XPath xpath = factory.newXPath();

xpath.setNamespaceContext(new PersonalNamespaceContext());

XPathExpression expr

= xpath.compile("//pre:book[pre:author='Neal Stephenson']/pre:title/text()");

Object result = expr.evaluate(doc, XPathConstants.NODESET);

NodeList nodes = (NodeList) result;

for (int i = 0; i < nodes.getLength(); i++) {

Trang 16

đơn giản được (Các hàm XPath có thể được đánh giá theo nhiều cách và nhiều thời điểm khác nhau.)

Các hàm mở rộng thực hiện truy cập thông qua Java XPath API phải thực thi được giao diện javax.xml.xpath.XPathFunction Giao diện này khai báo một phương thức dánh giá đơn giản:

public Object evaluate(List args) throws XPathFunctionException

Phương thức này nên trả lại một trong năm kiểu giá trị mà ngôn ngữ Java để có thể chuyển đổi được sang XPath:

Ví dụ 8 Hàm mở rộng XPath dành cho việc kiểm tra ISBNs

import java.util.List;

import javax.xml.xpath.*;

Trang 17

import org.w3c.dom.*;

public class ISBNValidator implements XPathFunction {

// This class could easily be implemented as a Singleton

if (o instanceof String) isbn = (String) args.get(0);

else if (o instanceof Boolean) isbn = o.toString();

else if (o instanceof Double) isbn = o.toString();

else if (o instanceof NodeList) {

NodeList list = (NodeList) o;

Ngày đăng: 07/08/2014, 10:22

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w