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

Sử dụng đối tượng NamespaceContext của ngôn ngữ Java với XPath Các phương thức để phân tích các không gian tên với API của Java pdf

28 264 0
Tài liệu đã được kiểm tra trùng lặp

Đ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 28
Dung lượng 210,2 KB

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

Nội dung

Sử dụng đối tượng NamespaceContext của ngôn ngữ Java với XPath Các phương thức để phân tích các không gian tên với API của Java Holger Kraus, Chuyên gia IT, IBM Tóm tắt: Nếu bạn muốn dù

Trang 1

Sử dụng đối tượng NamespaceContext của ngôn ngữ Java với XPath

Các phương thức để phân tích các không gian tên với API của Java

Holger Kraus, Chuyên gia IT, IBM

Tóm tắt: Nếu bạn muốn dùng các không gian tên trong các biểu thức XPath, bạn

phải cung cấp đường dẫn của tiền tố được sử dụng cho URI của không gian tên Bài viết này mô tả ba biến thể của việc cung cấp tiền tố cho ánh xạ không gian tên Bài này có các đoạn mã mẫu giúp bạn dễ dàng viết mã cho NamespaceContext Điều kiện tiên quyết và ví dụ

Trong bài này, tôi giả sử rằng bạn đã quen với các chi tiết kỹ thuật được mô tả trong "Đánh giá XPath từ nền tảng Java™" do Brett McLaughlin viết Nếu bạn chưa biết cách thực thi các chương trình Java sử dụng XPath, xin vui lòng tham khảo bài viết của Brett (tìm thấy ở Tài nguyên.) Và bạn cũng đã biết các hàm API cần thiết để đọc tệp XML và để đánh giá biểu thức XPath

Bạn sẽ dùng tệp XML sau cho tất cả các ví dụ trong bài:

Trang 2

 API: Giao diện lập trình ứng dụng

 DOM: Mô hình đối tượng tài liệu

 URI: Định danh tài nguyên tổng quát

 XHTML: Ngôn ngữ đánh dấu siêu văn bản mở rộng

 XML: Ngôn ngữ đánh dấu mở rộng

 XSD: Định nghĩa lược đồ XML

Trang 3

 XSLT: Chuyển đổi ngôn ngữ định kiểu mở rộng

Điều thú vị thứ hai về XML mẫu này là thành phần booklist có ba thành phần con, tất cả có tên là book Nhưng thành phần con đầu tiên có không gian tên là science, trong khi thành phần con khác có không gian tên là fiction Điều này có nghĩa là, những thành phần này là khác nhau đối với XPath Bạn sẽ thấy các hệ quả trong các ví dụ tiếp theo

Cũng cần phải nói trước, đoạn mã không được tối ưu hóa cho việc bảo trì nhưng

nó dễ đọc Có nghĩa là nó có một số chỗ dư thừa Kết quả được đưa ra bằng cách đơn giản nhất thông qua System.out.println() Tất cả các dòng của đoạn mã liên quan đến kết quả được viết tắt với ' ' trong bài viết Tôi cũng không đề cập đến phương thức trợ giúp (helper) trong bài này, nhưng chúng đi kèm trong tệp tải về (Xem Tải về)

Không gian tên được xác định bởi URI (trong ví dụ này,

http://univNaSpResolver/booklist) Để tránh việc sử dụng chuỗi dài như thế, bạn định nghĩa một tiền tố (prefix) mà gắn với URI này (trong ví dụ này, books) Xin nhớ rằng tiền tố cũng giống như một biến: tên của nó không thành vấn đề Nếu hai tiền tố cùng tham chiếu tới một URI, không gian tên của các thành phần gắn với tiền tố sẽ giống nhau (xem ví dụ 1 trong Ví dụ 5)

Một biểu thức XPath sử dụng các tiền tố (ví dụ, books:booklist/science:book) và, bạn phải cung cấp URI gắn với mỗi tiền tố Đây là nơi mà NamespaceContext xuất hiện Nó làm những việc đó

Bài viết này giải thích các cách khác nhau để cung cấp ánh xạ giữa tiền tố và URI

Trang 4

Trong tệp XML, ánh xạ được cung cấp bởi thuộc tính xmlns như:

xmlns:books="http://univNaSpResolver/booklist" hoặc

xmlns="http://univNaSpResolver/book" (không gian tên mặc định)

Sự cần thiết của việc cung cấp sự phân giải không gian tên

Nếu bạn có XML mà sử dụng các không gian tên, một biểu thức XPath sẽ thất bại nếu bạn không cung cấp một NamespaceContext Ví dụ 0 trong Ví dụ 2 minh họa trường hợp này Đối tượng XPath được xây dựng và ước lượng trên tài liệu XML Đầu tiên, thử viết biểu thức mà không có các tiền tố không gian tên (result1) Trong phần hai, viết biểu thức với các tiền tố không gian tên result2)

Ví dụ 2 Ví dụ 0 mà không có sự phân giải không gian tên

private static void example0(Document example)

throws XPathExpressionException, TransformerException {

sysout("\n*** Zero example - no namespaces provided ***");

XPath xPath = XPathFactory.newInstance().newXPath();

NodeList result1 = (NodeList) xPath.evaluate("booklist/book", example, XPathConstants.NODESET);

NodeList result2 = (NodeList) xPath.evaluate(

"books:booklist/science:book", example, XPathConstants.NODESET);

Trang 5

}

Kết quả như sau

Ví dụ 3 Kết quả từ ví dụ 0

*** Zero example - no namespaces provided ***

First try asking without namespace prefix:

Sự phân giải không gian tên được viết sẵn trong mã

Hoàn toàn có thể cung cấp các không gian tên như là các giá trị có sẵn trong mã cái mà trông giống như lớp trong Ví dụ 4:

Trang 6

Ví dụ 4 Sự phân giải không gian tên được viết sẵn

public class HardcodedNamespaceResolver implements NamespaceContext {

Trang 7

public String getPrefix(String namespaceURI) {

// Not needed in this context

return null;

}

public Iterator getPrefixes(String namespaceURI) {

// Not needed in this context

Trang 8

Ví dụ 5 Ví dụ 1 với sự phân giải không gian tên được viết sẵn trong mã

private static void example1(Document example)

throws XPathExpressionException, TransformerException {

sysout("\n*** First example - namespacelookup hardcoded ***");

XPath xPath = XPathFactory.newInstance().newXPath();

NodeList result2 = (NodeList) xPath.evaluate(

"books:booklist/fiction:book", example, XPathConstants.NODESET);

String result = xPath.evaluate("books:booklist/technical:book/:author", example);

}

Trang 9

Kết quả như sau

Ví dụ 6 Kết quả từ ví dụ 1

*** First example - namespacelookup hardcoded ***

Using any namespaces results in a NodeList:

> books:booklist/technical:book

Number of Nodes: 1

<?xml version="1.0" encoding="UTF-8"?>

<science:book xmlns:science="http://univNaSpResolver/sciencebook"> <title xmlns="http://univNaSpResolver/book">Learning XPath</title> <author xmlns="http://univNaSpResolver/book">Michael Schmidt</author> </science:book>

> books:booklist/fiction:book

Number of Nodes: 2

<?xml version="1.0" encoding="UTF-8"?>

<fiction:book xmlns:fiction="http://univNaSpResolver/fictionbook">

<title xmlns="http://univNaSpResolver/book">Faust I</title>

<author xmlns="http://univNaSpResolver/book">Johann Wolfgang von Goethe</author>

</fiction:book>

Trang 10

<?xml version="1.0" encoding="UTF-8"?>

<fiction:book xmlns:fiction="http://univNaSpResolver/fictionbook">

<title xmlns="http://univNaSpResolver/book">Faust II</title>

<author xmlns="http://univNaSpResolver/book">Johann Wolfgang von

Đọc các không gian tên từ tài liệu

Các không gian tên và các tiền tố của chúng được ghi chép trong các tệp XML, do

đó bạn có thể sử dụng chúng từ đó Cách dễ nhất là ủy nhiệm việc tìm kiếm cho tài liệu

Ví dụ 7 Sự phân giải không gian tên trực tiếp từ tài liệu

public class UniversalNamespaceResolver implements NamespaceContext {

Trang 12

public Iterator getPrefixes(String namespaceURI) {

// not implemented yet

return null;

}

}

Trang 13

Những điều đáng chú ý:

 Nếu tài liệu bị thay đổi trước khi XPath được dùng, sự thay đổi sẽ được thể hiện trong việc tìm kiếm của không gian tên, bởi vì sự ủy nhiệm được hoàn tất khi cần sử dụng phiên bản hiện tại của tài liệu

 Sự tìm kiếm các không gian tên hoặc các tiền tố được hoàn tất trong các nút tiền bối, trong trường hợp của chúng ta nút sourceDocument Điều này có nghĩa là, với đoạn mã được cung cấp, bạn chỉ lấy các không gian tên được

mô tả trong nút gốc Không gian tên science sẽ được tìm thấy trong ví dụ này

 Việc tìm kiếm được gọi khi XPath được ước lượng, vì vậy nó sẽ tiêu tốn thêm một chút thời gian

Đây là đoạn mã ví dụ:

Ví dụ 8 Ví dụ 2 với sự phân giải không gian tên trực tiếp từ tài liệu

private static void example2(Document example)

throws XPathExpressionException, TransformerException {

sysout("\n*** Second example - namespacelookup delegated to document

Trang 14

NodeList result1 = (NodeList) xPath.evaluate(

NodeList result2 = (NodeList) xPath.evaluate(

"books:booklist/fiction:book", example, XPathConstants.NODESET);

String result = xPath.evaluate(

Trang 15

Try to use the science prefix: no result

> books:booklist/science:book

The resolver only knows namespaces of the first level!

To be precise: Only namespaces above the node, passed in the constructor The fiction namespace is such a namespace:

> books:booklist/fiction:book

Number of Nodes: 2

<?xml version="1.0" encoding="UTF-8"?>

<fiction:book xmlns:fiction="http://univNaSpResolver/fictionbook"> <title xmlns="http://univNaSpResolver/book">Faust I</title>

<author xmlns="http://univNaSpResolver/book">Johann Wolfgang von Goethe</author>

</fiction:book>

<?xml version="1.0" encoding="UTF-8"?>

<fiction:book xmlns:fiction="http://univNaSpResolver/fictionbook"> <title xmlns="http://univNaSpResolver/book">Faust II</title>

<author xmlns="http://univNaSpResolver/book">Johann Wolfgang von Goethe</author>

Trang 16

Như bạn thấy trong kết quả, không gian tên được mô tả trong thành phần book với tiền tố science không được phân giải Phương thức ước lượng gửi trả lại một XPathExpressionException Để tránh vấn đề này, bạn có lẽ tách nốt science:book khỏi tài liệu và sử dụng nốt này như là sự ủy nhiệm Nhưng điều này có nghĩa bạn phải phân tích thêm tài liệu và không hiệu quả cho lắm

Đọc các không gian tên từ tài liệu và lưu trữ trong vùng đệm

Phiên bản tiếp theo này của NamespaceContext thì tốt hơn Nó đọc các không gian tên chỉ một lần trong phương thức khởi tạo Mọi lời gọi cho một không gian tên đều được trả lời từ một vùng đệm Và kết quả, một sự thay đổi trong tài liệu không ảnh hưởng khi mà danh sách các không gian tên được lưu trữ tạm thời tại thời điểm tạo đối tượng Java

Ví dụ 10 Lưu trữ sự phân giải không gian tên trong vùng đệm từ tài liệu

public class UniversalNamespaceCache implements NamespaceContext {

private static final String DEFAULT_NS = "DEFAULT";

private Map<String, String> prefix2Uri = new HashMap<String, String>(); private Map<String, String> uri2Prefix = new HashMap<String, String>();

/**

* This constructor parses the document and stores all namespaces it can

* find If toplevelOnly is true, only namespaces in the root are used

*

* @param document

* source document

Trang 17

System.out.println("The list of the cached namespaces:");

for (String key : prefix2Uri.keySet()) {

Trang 18

NamedNodeMap attributes = node.getAttributes();

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

Node attribute = attributes.item(i);

storeAttribute((Attr) attribute);

}

if (!attributesOnly) {

NodeList chields = node.getChildNodes();

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

Node chield = chields.item(i);

if (chield.getNodeType() == Node.ELEMENT_NODE) examineNode(chield, false);

Trang 19

*/

private void storeAttribute(Attr attribute) {

// examine the attributes in namespace xmlns

} else {

// The defined prefixes are stored here

putInCache(attribute.getLocalName(), attribute.getNodeValue()); }

Trang 20

public String getNamespaceURI(String prefix) {

if (prefix == null || prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) {

Trang 21

public String getPrefix(String namespaceURI) {

toplevelOnly trong phương thức khởi tạo được đặt là true Nếu biến logic được đặt

là false, sự xem xét các nút con sẽ được bắt đầu sau khi các thuộc tính được lưu trữ Một điều về đoạn mã cần cân nhắc: Trong DOM, nút đầu tiên sẽ biểu diễn tài liệu như là toàn bộ, vì vậy, để lấy các thành phần book để đọc các không gian tên, bạn phải đi đến nút con một cách chính xác

Trong trường hợp này, sử dụng NamespaceContext thì đơn giản hơn:

Ví dụ 11 Ví dụ 3 với sự phân giải không gian tên được lưu trữ tạm thời (chỉ cấp độ cao nhất)

private static void example3(Document example)

Trang 22

throws XPathExpressionException, TransformerException {

sysout("\n*** Third example - namespaces of toplevel node cached ***");

XPath xPath = XPathFactory.newInstance().newXPath();

xPath.setNamespaceContext(new UniversalNamespaceCache(example, true));

NodeList result2 = (NodeList) xPath.evaluate(

"books:booklist/fiction:book", example, XPathConstants.NODESET);

String result = xPath.evaluate(

"books:booklist/fiction:book[1]/:author", example);

Trang 23

*** Third example - namespaces of toplevel node cached ***

The list of the cached namespaces:

prefix DEFAULT: uri http://univNaSpResolver/book

prefix fiction: uri http://univNaSpResolver/fictionbook

prefix books: uri http://univNaSpResolver/booklist

Try to use the science prefix:

> books:booklist/science:book

The cache only knows namespaces of the first level!

The fiction namespace is such a namespace:

> books:booklist/fiction:book

Number of Nodes: 2

<?xml version="1.0" encoding="UTF-8"?>

<fiction:book xmlns:fiction="http://univNaSpResolver/fictionbook">

Trang 24

<title xmlns="http://univNaSpResolver/book">Faust I</title>

<author xmlns="http://univNaSpResolver/book">Johann Wolfgang von

Goethe</author>

</fiction:book>

<?xml version="1.0" encoding="UTF-8"?>

<fiction:book xmlns:fiction="http://univNaSpResolver/fictionbook">

<title xmlns="http://univNaSpResolver/book">Faust II</title>

<author xmlns="http://univNaSpResolver/book">Johann Wolfgang von

tố science không thể được phân giải Biểu thức XPath trả lại một ngoại lệ

Trang 25

lồng nhau trong các URI khác nhau), tiền tố nào tìm thấy cuối cùng sẽ chiến thắng Trong thực tế, điều này ít khi xảy ra

Sử dụng NamespaceContext trong ví dụ này cũng giống như trong các ví dụ trước Biến logic toplevelOnly trong phương thức khởi tạo phải được đặt là false

Ví dụ 13 Ví dụ 4 với sự phân giải không gian tên được lưu trữ trong vùng đêm (tất cả các cấp độ)

private static void example4(Document example)

throws XPathExpressionException, TransformerException {

sysout("\n*** Fourth example - namespaces all levels cached ***");

XPath xPath = XPathFactory.newInstance().newXPath();

xPath.setNamespaceContext(new UniversalNamespaceCache(example,

false));

NodeList result1 = (NodeList) xPath.evaluate(

"books:booklist/science:book", example, XPathConstants.NODESET);

NodeList result2 = (NodeList) xPath.evaluate(

"books:booklist/fiction:book", example, XPathConstants.NODESET);

String result = xPath.evaluate(

"books:booklist/fiction:book[1]/:author", example);

Trang 26

}

Kết quả như sau:

Ví dụ 14 Kết quả từ ví dụ 4

*** Fourth example - namespaces all levels cached ***

The list of the cached namespaces:

prefix science: uri http://univNaSpResolver/sciencebook

prefix DEFAULT: uri http://univNaSpResolver/book

prefix fiction: uri http://univNaSpResolver/fictionbook

prefix books: uri http://univNaSpResolver/booklist

Now the use of the science prefix works as well:

> books:booklist/science:book

Number of Nodes: 1

<?xml version="1.0" encoding="UTF-8"?>

<science:book xmlns:science="http://univNaSpResolver/sciencebook"> <title xmlns="http://univNaSpResolver/book">Learning XPath</title> <author xmlns="http://univNaSpResolver/book">Michael Schmidt</author> </science:book>

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