11 Xử lý XML dễ dàng và hiệu quả: Nâng cấp lên JAXP 1.3 - Phần 3

(Đăng ngày 30/06/2006) Việc xác thực tài liệu XML dựa trên một lược đồ không đáng tin cậy có thể gây ra những hậu quả nghiêm trọng, vì việc xác thực có thể sửa đổi dữ liệu thực bằng cách thêm các thuộc tính mặc định và có thể làm hỏng dữ liệu. Việc xác thực dựa trên một lược đồ không đáng tin cậy cũng có thể có nghĩa là một tài liệu phiên bản đến có thể không tuân theo các ràng buộc hoặc quy tắc của doanh nghiệp bạn.

Xác thực DOM trong bộ nhớ

Các API chuyển đổi cũng cho phép thu được kết quả đã biến đổi dưới dạng một DOMđối tượng. Đối DOMtượng trong bộ nhớ có thể được xác thực dựa trên một lược đồ. Điều này có thể được thực hiện như sau:

DOMResult dr = new DOMResult ();t.transform (xml, dr);DOMSource ds = new DOMSource ();schema.newValidator (). validate (ds (dr.getNode ()));

Vì vậy, bạn thấy rằng các API xác thực có thể được sử dụng với các API chuyển đổi để thực hiện những việc phức tạp một cách dễ dàng. Cách tiếp cận này cũng tăng cường hiệu suất vì nó tránh được bước phân tích cú pháp lại XML khi xác thực tài liệu XML đã được chuyển đổi.

Xác thực tài liệu JDOM

Có ValidatorHandler thể được sử dụng để xác thực các mô hình đối tượng khác nhau, chẳng hạn như JDOMđối với (các) lược đồ. Trên thực tế, bất kỳ mô hình đối tượng nào ( XOM, DOM4Jv.v.) có thể được xây dựng bên trên SAX luồng hoặc có thể phát ra SAX các sự kiện đều có thể được sử dụng với Khung xác thực lược đồ để xác thực tài liệu XML dựa trên một lược đồ. Điều này là có thể vì ValidationHandlercó thể xác thực một SAXluồng.

Hãy xem cách một JDOM tài liệu có thể được xác thực dựa trên (các) lược đồ:

SAXOutputter so = new SAXOutputter (vh);so.output (jdomDocument);

Nó là đơn giản. JDOM có một cách để xuất một JDOM tài liệu dưới dạng một luồng SAX sự kiện. SAXOutputter kích hoạt SAX các sự kiện được xác thực bởi ValidatorHandler. Bất kỳ lỗi nào gặp phải đều được báo cáo qua ErrorHandler set on ValidatorHandler.

Nhận thông tin loại lược đồ

ValidatorHandler có thể cấp quyền truy cập TypeInfoProvider, có thể được truy vấn để truy cập thông tin loại được xác định bởi trình xác nhận. Đối tượng này có bản chất động và trả về thông tin kiểu của phần tử hoặc thuộc tính hiện tại được đánh giá bởi ValidationHandlerquá trình xác thực tài liệu XML. Giao diện này cho phép ứng dụng biết ba điều:

  • Thuộc tính có được khai báo là một IDkiểu hay không
  • Thuộc tính đã được khai báo trong tài liệu XML ban đầu hay được thêm vào Validator trong quá trình xác thực
  • Loại thông tin của phần tử hoặc thuộc tính được khai báo trong lược đồ được liên kết với tài liệu

Thông tin kiểu được trả về dưới dạng một org.w3c.dom.TypeInfo đối tượng, được định nghĩa là một phần của DOM L3. Các TypeInfo đối tượng quay trở lại là không thay đổi, và người gọi có thể giữ tham chiếu đến đối tượng TypeInfo thu được dài hơn phạm vi callback. Các phương thức của giao diện này chỉ có thể được gọi trong startElement trường hợp ContentHandler ứng dụng đặt trên ValidatorHandler. Ví dụ, hãy xem phần mã bên dưới. (Lưu ý: Để rõ ràng, chỉ một phần của mã được hiển thị ở đây. Để có nguồn hoàn chỉnh, hãy xem SchemaTypeInformation.java mẫu , có thể tải xuống từ đây .)

ValidatorHandler vh = schema.newValidatorHandler (); vh.setErrorHandler (eh);vh.setContentHandler (MyContentHandler mới ( vh.getTypeInfoProvider ()));SAXParserFactory spf = SAXParserFactory.newInstance ();spf.setNamespaceAware (true);Trình đọc XMLReader = spf.newSAXParser (). GetXMLReader ();reader.setContentHandler (vh);reader.parse ();

Đảm bảo bảo mật dữ liệu

Việc xác thực tài liệu XML dựa trên một lược đồ không đáng tin cậy có thể gây ra những hậu quả nghiêm trọng, vì việc xác thực có thể sửa đổi dữ liệu thực tế bằng cách thêm các thuộc tính mặc định và có thể làm hỏng dữ liệu. Việc xác thực dựa trên một lược đồ không đáng tin cậy cũng có thể có nghĩa là một tài liệu phiên bản đến có thể không tuân theo các ràng buộc hoặc quy tắc của doanh nghiệp bạn.

Với các API xác thực mới, lấy một Schema phiên bản là bước đầu tiên trước khi có thể xác thực một tài liệu cá thể và chính ứng dụng sẽ xác định cách tạo Schemaphiên bản. Việc xác thực bằng cách sử dụng Schema cá thể đảm bảo rằng một tài liệu cá thể đến không được xác thực đối với bất kỳ (các) lược đồ (không đáng tin cậy) nào khác mà chỉ chống lại (các) lược đồ mà từ đó phiên bản được tạo. Nếu tài liệu XML phiên bản có các phần tử hoặc thuộc tính tham chiếu đến (các) lược đồ từ một thứ khác targetNamespace và không phải là một phần của javax.xml.validation.Schema biểu diễn, một lỗi sẽ được đưa ra. Cách tiếp cận này bảo vệ bạn khỏi những sai lầm ngẫu nhiên và tài liệu độc hại.

Sử dụng lại phiên bản phân tích cú pháp

Có thể sử dụng cùng một phiên bản phân tích cú pháp để phân tích cú pháp nhiều tài liệu XML không? Điều này không rõ ràng và hành vi phụ thuộc vào việc triển khai. JAXP 1.3 đã bổ sung chức năng mới reset() trên SAXParser, DocumentBuildervà Transformer. Điều này đảm bảo rằng cùng một phiên bản có thể được sử dụng lại. Các reset chức năng cải thiện hiệu suất tổng thể bằng cách tiết kiệm nguồn lực, thời gian gắn liền với việc tạo ra các trường hợp bộ nhớ, và thời gian thu gom rác thải. Hãy xem reset()hàm có thể được sử dụng như thế nào .

SAXParserFactory spf = SAXParserFactory.newInstance ();spf.setSchema (lược đồ);SAXParser saxParser = spf.newSAXParser ();for (int i = 0; i <n; i ++) {saxParser.parse (Tệp mới (args [i]), myHandler);saxParser.reset (); }

Chức năng tương tự cũng đã được thêm vào thiết kế mới javax.xml.validation.Validator, cũng như javax.xml.xpath.XPath. Ứng dụng được khuyến khích tái sử dụng parser, transformer, validatorvà dụ XPath bằng cách gọi reset() khi xử lý nhiều tài liệu XML. Lưu ý rằng reset()đặt phiên bản về cài đặt gốc.

Hỗ trợ XPath

Việc truy cập XML được thực hiện đơn giản bằng XPath: Một biểu thức XPath duy nhất có thể được sử dụng để thay thế nhiều dòng DOM mã API. JAXP 1.3 đã xác định các API XPath phù hợp với đặc tả XPath 1.0 và cung cấp các API trung lập mô hình đối tượng để đánh giá các biểu thức XPath và truy cập vào môi trường đánh giá. Mặc dù các API hiện tại tuân theo XPath 1.0, các API đã được thiết kế với sự hỗ trợ XPath 2.0 trong tương lai.

Để sử dụng các API JAXP 1.3 XPath, bước đầu tiên là lấy phiên bản của XPathFactory. Mặc dù mô hình mặc định là W3C DOM, nó có thể được thay đổi bằng cách chỉ định URI mô hình đối tượng:

Nhà máy XPathFactory = XPathFactory.newInstance ();Nhà máy XPathFactory = XpathFactory.newInstance ( );

Đánh giá biểu thức XPath

XpathFactory được sử dụng để tạo XPath các đối tượng. Các XPath giao diện cung cấp quyền truy cập vào môi trường đánh giá XPath và biểu thức. XPathđã quá tải evaluate()hàm, có thể trả về kết quả bằng cách đánh giá biểu thức XPath dựa trên kiểu trả về do ứng dụng đặt. Ví dụ, hãy xem tài liệu XML sau:

     Tác giả1      Tên1      ISBN1      Tác giả2      Tên2      ISBN2

Sau đây là mã làm việc để đánh giá biểu thức XPath và in nội dung của tất cả các Book phần tử trong tài liệu XML:

XPath xpath = XpathFactory.newInstance (). NewXPath ();Biểu thức chuỗi = “/ Books / Book / Name / text ()”;NodeSet nameNodes = (NodeSet) xpath.evaluate (biểu thức, mới InputSource (“Books.xml”), XpathConstants.NODESET);// in tất cả tên của sáchfor (int i = 0; i <result.getLength (); i ++) {    System.out.println (“Tên sách” + (i + 1) + “là” +    result.item (i) .getNodeValue ());}

Đánh giá với ngữ cảnh được chỉ định

XPath cũng có khả năng đánh giá một biểu thức dựa trên ngữ cảnh do ứng dụng thiết lập. Ví dụ sau đặt Documentnút làm bối cảnh để đánh giá:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance ();DocumentBuilder db = dbf.newDocumentBuilder ();Document d = db.parse (new File (“Books.xml”));XPath xpath = XPathFactory.newInstance (). NewXPath ();Chuỗi exp = “/ Sách / Sách”;Sách NodeSet = (NodeSet) xpath.evaluate (exp, d, XpathConstants.NODESET);

Với tham chiếu đến một Book phần tử, một biểu thức XPath tương đối bây giờ có thể được viết để chọn Namephần tử như sau:

Biểu thức chuỗi = “Tên”;Node book = xpath.evaluate (exp, books.item (0) , XpathConstants.NODE);

Đánh giá NamespaceContext XPath

Điều gì xảy ra nếu tài liệu XML nhận biết được không gian tên? Hãy xem tài liệu XML sau, trong đó Book phần tử đầu tiên nằm trong publisher1 miền và phần tử thứ hai trong publisher2 miền:

     Tác giả1     Tên1     ISBN1     Tác giả2     Tên2     ISBN2     Cứng

Trong trường hợp này, biểu thức XPath /Books/Book/Name/text() sẽ không cho bất kỳ kết quả nào vì biểu thức không đủ điều kiện. Bạn có thể sử dụng một biểu thức chẳng hạn như /Books/p1:Book/p1:Namevới một p1tiền tố. Tuy nhiên, bạn nên đặt NamespaceContext trên XPath phiên bản để p1 tiền tố có thể được giải quyết. Trong ví dụ sau, NamespaceContextkhả năng phân giải p1được đặt trên XPath phiên bản. Lưu ý rằng hai Book phần tử nằm trong các không gian tên khác nhau, vì vậy biểu thức sẽ chỉ dẫn đến một nút.

XPath xpath = XpathFactory.newInstance (). NewXPath ();String exp = “/ Books / p1: Book / p1: Name”;xpath.setNamespaceContext (MyNamespaceContext mới ());InputSource is = new InputSource (“Books.xml”);NodeSet nn = (NodeSet) xpath.evaluate (exp, là, XpathConstants.NODESET);// In số đếm.System.out.println (“Số nút =” + nn.getLength ());

XPathVariableResolver

Đặc tả XPath cho phép các biến được sử dụng trong các biểu thức XPath. XPathVariableResolver được định nghĩa để cung cấp quyền truy cập vào tập hợp các biến XPath do người dùng định nghĩa. Đây là một ví dụ về biểu thức XPath sử dụng Variable:

String exp = “/ Books / j: Book [j: Name = $ bookName]”;xpath.setXPathVariableResolver ( new SimpleXPathVariableResolver ());InputSource is = new InputSource (“Books.xml”);Node n = (Node) xpath.evaluate (exp, là, XPathConstants.NODE);System.out.println (“Tên nút là” + n.getNodeName ());

A SimpleXPathVariableResolver có thể thực hiện resolveVariable() chức năng như sau. (Lưu ý: Để rõ ràng, chỉ mã liên quan được hiển thị ở đây.)

public Object ResolutionVariable (javax.xml.namespace.QName qName){    if (qName.getLocalPart (). equals (“bookName”))        return “Tên1”;         ….    }}

Các kiểu dữ liệu lược đồ XML

JAXP 1.3 đã giới thiệu các kiểu dữ liệu mới trong nền tảng Java, javax.xml.datatypesgói, ánh xạ trực tiếp đến một số kiểu dữ liệu lược đồ XML, do đó mang hỗ trợ kiểu dữ liệu lược đồ XML trực tiếp vào nền tảng Java.

Các DatatypeFactory có chức năng để tạo ra các loại khác nhau của các kiểu dữ liệu – ví dụ, xs:data, xs:dateTime, xs:duration, và vân vân. Các javax.xml.datatype.XMLGregorianCalendar chăm sóc nhiều Schema W3C XML 1,0 ngày và thời gian các kiểu dữ liệu, đặc biệt là dateTime, time, date, gYearMonth, gMonthDay, gYear gMonth, và gDayđược định nghĩa trong namespace XML này:

http://www.w3.org/2001/XMLSchema

Các kiểu dữ liệu này được định nghĩa chuẩn trong Lược đồ XML W3C 1.0, Phần 2, Mục 3.2.7-14 .

Kiểu dữ liệu javax.xml.validation.Duration là một biểu diễn bất biến của khoảng thời gian như được định nghĩa trong đặc tả Lược đồ XML của W3C 1.0. Một Duration đối tượng đại diện cho một khoảng thời gian Gregorian, bao gồm sáu trường (năm, tháng, ngày, giờ, phút và giây) cũng như một trường ký hiệu (+ hoặc -).

Bảng 1 cho thấy ánh xạ của các kiểu dữ liệu lược đồ XML sang các kiểu dữ liệu nền tảng Java. Bảng 2 cho thấy ánh xạ của các kiểu dữ liệu XPath và kiểu dữ liệu Nền tảng Java.

Bảng 1. Lược đồ XML và ánh xạ kiểu dữ liệu nền tảng Java
Loại dữ liệu lược đồ XML W3CLoại dữ liệu nền tảng Java
xs:dateXMLGregorianCalendar
xs:dateTimeXMLGregorianCalendar
xs:durationDuration
xs:gDayXMLGregorianCalendar
xs:gMonthXMLGregorianCalendar
xs:gMonthDayXMLGregorianCalendar
xs:gYearXMLGregorianCalendar
xs:gYearMonthXMLGregorianCalendar
xs:timeXMLGregorianCalendar
Bảng 2. Ánh xạ kiểu dữ liệu nền tảng XPath và Java
Kiểu dữ liệu XPathLoại dữ liệu nền tảng Java
xdt:dayTimeDurationDuration
xdt:yearMonthDurationDuration

Các kiểu dữ liệu này có một tập hợp các hàm phong phú được giới thiệu để thực hiện các phép toán cơ bản đối với các kiểu dữ liệu, chẳng hạn như cộng, trừ và nhân.

Ngoài ra, có nhiều cách để lấy lexicalRepresentation kiểu dữ liệu cụ thể được định nghĩa tại Lược đồ XML 1.0, Phần 2, Phần 3.2. [7-14] .1, Biểu diễn Lexical . Không cần phải hiểu sự phức tạp của các kiểu dữ liệu lược đồ XML chẳng hạn như loại phép toán nào được phép trên một kiểu dữ liệu, cách viết biểu diễn từ vựng, v.v. Các javax.xml.datatype API đã xác định một tập hợp các hàm phong phú để giúp bạn dễ dàng.

Hỗ trợ XInclude

JAXP 1.3 cũng đã xác định hỗ trợ cho XInclude. SAXParserFactory/DocumentBuilderFactory nên được cấu hình để làm cho nó nhận biết được XInclude. Làm điều này bằng cách đặt setXIncludeAware()thành true.

Cải tiến bảo mật

JAXP 1.3 đã xác định một tính năng bảo mật:

http: //javax.xml.XMLConstants/feature/secure-processing

Khi được đặt thành true, điều này sẽ vận hành trình phân tích cú pháp theo cách an toàn và hướng dẫn việc triển khai xử lý XML một cách an toàn và tránh các điều kiện như tấn công từ chối dịch vụ. Các ví dụ bao gồm hạn chế số lượng thực thể có thể được mở rộng, số lượng thuộc tính mà một phần tử có thể có và các cấu trúc lược đồ XML sẽ tiêu thụ một lượng lớn tài nguyên, chẳng hạn như các giá trị lớn cho minOccursvà maxOccurs. Nếu quá trình xử lý XML bị giới hạn vì lý do bảo mật, nó sẽ được báo cáo bằng một cuộc gọi đến người đã đăng ký ErrorHandler.fatalError().

Tóm lược

Bài viết này đã giới thiệu cho bạn một số tính năng mới trong JAXP 1.3. Bạn đã thấy những lợi ích của Khung xác thực lược đồ và thấy cách nó có thể được sử dụng để cải thiện hiệu suất của việc xác thực lược đồ. Các nhà phát triển làm việc với các ứng dụng sử dụng thuộc tính lược đồ JAXP 1.2 để xác thực tài liệu XML dựa trên các lược đồ nên nâng cấp lên JAXP 1.3 và sử dụng khuôn khổ này. Hãy nhớ sử dụng lại phiên bản phân tích cú pháp bằng cách gọi reset()phương thức để cải thiện hiệu suất.

Các API XPath trung lập đối tượng-mô hình-đối tượng mới hỗ trợ XPath và có thể hoạt động với các mô hình đối tượng khác nhau. Hỗ trợ kiểu dữ liệu lược đồ XML được đưa trực tiếp vào nền tảng Java với sự ra đời của các kiểu dữ liệu mới. Các tính năng bảo mật được giới thiệu trong JAXP 1.3 có thể giúp bảo vệ ứng dụng khỏi các cuộc tấn công từ chối dịch vụ. Ngoài ra, JAXP 1.3 cung cấp hỗ trợ hoàn chỉnh cho các tiêu chuẩn mới nhất: XML 1.1, DOM L3, XInclude và SAX 2.0.2. Đây là đủ lý do để nâng cấp lên JAXP 1.3 và việc triển khai có sẵn để tải xuống từ java.net

Neeraj Bajaj

FPT Aptech trực thuộc Tổ chức Giáo dục FPT có hơn 25 năm kinh nghiệm đào tạo lập trình viên quốc tế tại Việt Nam, và luôn là sự lựa chọn ưu tiên của các sinh viên và nhà tuyển dụng.
0981578920
icons8-exercise-96