Thứ Năm, 13 tháng 10, 2016

Sử dụng SAX Parser để tìm kiếm dữ liệu

Sử dụng SAX Parser để tìm kiếm dữ liệu

Mục đích: Chủ đề của bài này giới thiệu về bộ SAX (Simple API for XML) Parser dùng để tìm kiếm và truy vấn dữ liệu trực tiếp trên tài liệu XML. Với tính đơn giản, dễ sử dụng nhưng đòi hỏi tính logic cao trong quá trình xử lý để tìm kiếm dữ liệu một cách nhanh chóng và hỗ trợ ứng dụng chạy trên hệ thống có bộ nhớ không lớn. Trong bài, chúng tôi sẽ hướng dẫn quí vị xây dựng ứng dụng sử dụng SAX để quí vị có thể vận dụng những khái niêm đã được nêu ra

Yêu cầu về kiến thức cơ bản

  • Nắm vững các khái niệm về XML và cách viết tài liệu XML well-formed (tham khảo lại bài Giới thiệu về XML – định nghĩa, cách viết XML đúng cú pháp (XML well-formed) http://www.kieutrongkhanh.net/2016/08/gioi-thieu-ve-xml-inh-nghia-cach-viet.html)
  • Nắm vững về cách xây dựng ứng dụng web và các khái niệm liên quan về Servlet (tham khảo tại địa chỉ http://www.kieutrongkhanh.net/search/label/Servlet%26JSP )
  • Nắm vững khái niệm về ngôn ngữ lập trình Java, lập trình thao tác hướng đối tượng
  • Đã viết và kiểm tra một tài liệu XML well-formed
  • Nắm vững cách xây dựng web sử dụng mô hình MVC với J2EE/JavaEE
  • Tools sử dụng ở đây là Netbeans 6.9.1 với JDK 6 update 22 hay Netbeans 7.3.1 với JDK 7 update 45 hay Netbeans 8.1 với JDK 8 update 66

Kiến thức tổng quát

  • SAX – là bộ parser thực hiện parsing tài liệu XML theo cơ chế như sau
    • Khi tài liệu XML được đưa vào bộ parser, toàn bộ tài liệu được kiểm tra well-formed
    • Khi nội dung tài liệu kiểm tra xong và đóng, toàn bộ tài liệu được biến thành Stringvà nạp trực tiếp vào trong bộ nhớ
    • Sau đó, bộ SAX parser sẽ thực hiện việc đọc chuỗi nạp trên bộ nhớ từ trái sang phải và dựa trên các biến cố qui định sẵn trong SAX và được người dùng cài đặt trong ContentHandler hay DefaultHandler, để thực hiện kích hoạt xử lý tương ứng theo nội dung đã được hiện thực
  • Một số điều cần lưu ý khi thực hiện với bộ SAX
    • SAX thực hiện parser với qui trình khi đã thực hiện là không dừng cho đến khi parse xong tài liệu XML. Do vậy, trong qua trình xử lý, chúng ta cần phải điều khiển cho quá trình xử lý có thể kích hoạt biến cố nhưng không thực hiện hành động để tăng performance cho ứng dụng
    • SAX là bộ parser chỉ parser từ đầu đến cuối – forward only – không thể quay lại node trước đó khi đã đi qua. Do vậy, chúng ta phải tiến hành đón nhận dữ liệu trước và sau đó mới xét kết quả để từ đó quyết định lưu trữ. Chúng ta không thể thực hiện việc xét điều kiện thỏa như logic thông thường và tiến hành lưu trữ.
    • SAX không chia sẻ đươc cho nhiều hơn một user hay chương trình trong quá trình xử lý
    • SAX chỉ thực hiện dựa trên tập ngữ nghĩa đã được định nghĩa sẵn – Language Resolved – với khoảng 11 biến cố
    • SAX là bộ xứ lý tuần tự và kích hoạt biến cố theo tập định nghĩa, cho nên dữ liệu trong quá trình parse phải được chúng ta xử lý lưu trữ, không thì dữ liệu sẽ mất (push parsing)
    • Content Handler là một interface được cung cấp đến cho người sử dụng với 11 biến cố để người dùng có thể implement xử lý tài liệu XML tùy theo mục đích của người sử dụng
    • Default Handler là một class được implement được ContentHandler, DTDHandler, ErrorsHandler và Language Resolver, cung cấp khả năng linh hoạt cho người dùng overriding những biến cố cần thiết để xử lý ứng dụng một cách tùy chọn theo mục đích của họ
    • Người phát triển ứng dụng thường áp dụng SAX để thực hiện tìm kiếm dữ liệu nhanh chóng và tiết kiệm bộ nhớ trong quá trình thực thi ứng dụng

Mô hình tổng quát

  • Cách thực áp dụng
    • Tạo đối tượng cung cấp API cho người dùng tương tác

SAXParserFactory spf = SAXParserFactory.newInstance();

SAXParser parser = spf.newSAXParser();

    • Cung cấp bộ xử lý của người dùng thông qua việc cài đặt class kế thừa hay implement từ Default Handler hay Content Handler

SAXHandlerInstance saxObj = new SAXHandlerInstance();

    • Thực hiện parse dữ liệu từ XML và xử lý

parser.parse(new File (xml_file_name), saxObj);

 

    • Xử lý kết quả từ saxObj sau khi quá trình parse hoàn tất
  • Tổng quát một xử lý tài liệu XML với các biến cố đơn giản

    • Với một ví dụ như hình trên, chúng ta nhận thấy
      • Chỉ với 5 biến cố: startDocument, endDocument, startElement, endElement, và characters là chúng ta đã xử lý được tại liệu đơn giản
      • Biến cố startDocument được kích hoạt khi parser đọc qua khỏi dòng xml declaration
      • Biến cố endDocument được kích hoạt khi parser đã tới end of file hay vị trí cuối cùng của element
      • Biến cố startElement được kích hoạt khi parser đọc xong một element hay một thẻ đóng tag của element. Parser sẽ trả vào trong methods giá trị của tên node - ở đây chính là qualifiedName – set default bộ SAX đang xem mọi element tuân thủ luật sử dụng qualifiedName với support namespace. Ngoài ra, parser còn đưa ra danh sách các thuộc tính, nếu không có thuộc tính nào, danh sách này tồn tại với số phần tử bằng 0
      • Biến cố endElement được kích hoạt khi parser được xong một thẻ đóng
      • Trong quá trình đọc startElement và endElement, parser không match với nhau vì theo mặc định tài liệu đã được kiểm tra well-formed rồi mới được parser
      • Biến cố character được kích hoạt khi gặp chuỗi không nằm trong thẻ bất kỳ nào – hay phần thân của thẻ XML – giữa thẻ đóng và thẻ mở hay giữa thẻ mở hay thẻ đóng. Do vậy, cần lưu ý xử lý tài liệu XML có định dạng với ký tự enter hay phím tab bất kỳ trong biến cố characters
  • Tập 11 biến cố cơ bản của SAX Parsers

Methods

Mô tả

startDocument

- public void startDocument () throws SAXException

- Xử lý khi bắt đầu parse tài liệu

endDocument

- public void endDocument () throws SAXException

- Xử lý khi bắt đầu parse chuẩn bị kết thúc tài liệu

startElement

- public void startElement (String uri, String localName,
                          String qName, Attributes atts) throws SAXException

- Xử lý khi đọc xong phần mở tag của element một node và đưa ra được uri nếu tài liệu có sử dụng namespace, tên element là localName, kết hợp tên prefix với local name là qName và tập attribute của node

endElement

- public void endElement (String uri, String localName,
                                                      String qName) throws SAXException

- Xử lý khi đọc xong phần đóng tag của một element

characters

- public void characters (char[] ch, int start, int length) throws                        
                                                                                             SAXException

- Xử lý khi đọc xong các chuỗi ký tự ngoài tag

ignorableWhitespace

- public void ignorableWhitespace (char[] ch, int start, int length)
                                                                     throws SAXException

- Xử lý khi đọc các ký tự whitespace và bỏ qua nó

processingInstruction

- public void processingInstruction (String target, String data) throws SAXException

- Xử lý khi đọc xong phần processing Instruction

setDocumentLocator

- public void setDocumentLocator (Locator locator)

- Lấy giá trị liên quan đến tài liệu đang parse cụ thể như là đường dẫn, vị trí cột hàng của các thành phần trong tài liệu

startPrefixMapping

- public void startPrefixMapping (String prefix, String uri) throws
                                                                                 SAXException

- Xử lý khi chạm được phần bắt đầu của prefix tại phần tag mở của một element

endPrefixMapping

- public void endPrefixMapping (String prefix) throws SAXException

- Xử lý khi chạm được phần kết thúc của prefix tại phần tag đóng của một element

skippedEntity

- public void skippedEntity (String name) throws SAXException

- Kích hoạt khi một entity không tìm thấy reference

Áp dụng lý thuyết trên nội dung phân tích dữ liệu cụ thể

  • Để áp dụng lý thuyết SAX, chúng tôi đưa ra bài ví dụ là áp dụng SAX để login và tìm kiếm trên tài liệu XML có dạng như sau

  • Các nội dung thực hiện theo từng bước như sau
    • Bước 1: Xây dựng thư viện hỗ trợ parsing tài liệu XML sử dụng SAX

  • Bước 2: Xây dựng giao diện thực hiện login

    • Bước 3: tạo handler để thực hiện xử lý
      • Tổng quan để login, chúng ta cần xử lý node students, nghĩa là chờ biến cố startElement của node được kích hoạt
      • Sau đó, trong startElement chúng ta sẽ lấy id chính là username để so sánh với giá trị người dùng nhập vào. Nếu giá trị trùng khớp chúng ta sẽ bật cờ đánh dấu là chúng ta đã đúng username
      • Khi username đã đúng, chúng ta mới đi xét giá trị của các thành phần con của node student, lần nữa chúng ta lại xử lý ở biến có startElement
      • Tuy nhiên, với các node này chúng ta cần phải lấy giá trị trong phần thân, nghĩa là chúng ta sẽ đón nhận trong biến cố characters. Tuy nhiên, trong characters chúng ta sẽ không biết đang ở xử lý ở tag nào. Do vậy, tại startElement chúng ta phải lưu tag chúng ta đang xử lý lại để tham chiếu khi xử lý characters
      • Chúng ta sẽ đón nhận full name, kiểm tra password, nếu password trùng khớp chúng ta sẽ bật cờ password lên đánh dấu và thiết lập các biến điều khiển trước đó là false
      • Khi password đã đúng, chúng ta tiếp tục kiểm tra giá trị khác dropout. Nếu khác, cờ tìm thấy bật lên, tất cả cờ khác tắt hết
      • Chúng ta biết rằng SAX chạy từ bắt đầu đến kết thúc không ngừng. Do vậy, chúng ta sẽ dùng cờ tìm thấy cuối cùng để tối ưu việc thực thi của SAX theo ngữ nghĩa chỉ xử lý khi chưa tìm thấy
      • Trong biến cố endElement để đảm bảo cho quá trình xử lý là đúng và không nhầm lẫn các chuỗi ký tự được parse trong character đến các element khác hay ngoài element. Chúng ta sẽ dùng biến cố element để đánh dấu tag xử lý hoàn tất bằng cách gán thành chuỗi rỗng
      • Tổng quát hóa, chúng ta sẽ implement 03 biến cố startElement, endElement và characters để xử lý check Login

  • Bước 4: Thực hiện xử lý trong Servlet để đưa ra kết quả
    • Tạo ProcessServlet

    • Bổ sung LoginSAXServlet

  • Bước 5: Clean and Build Project, Deploy, và chạy thử ứng dụng
    • Login với user đúng: id, password đúng và status là studying

 

    • Login với user đúng: id, password đúng và status là break

 

    • Login với user đúng nhưng status là drop out

 

    • Login với user không tồn tại

 

  • Chúng ta vừa hoàn tất xong chức năng login. Chúng ta sẽ tiếp tục với chứng năng search của SAX
    • Xây dựng đối tượng DTO để đón nhận kết quả khi xử lý Search trả về

    • Xây dựng Handler để xử lý kết quả Search
      • Trong nội dung xử lý này, chúng ta sẽ tạo ra một DTO mới tại biến cố startElement và ghi toàn bộ nội dung DTO này vào một list khi hoàn tất dữ liệu nghĩa là biến cố end Element
      • Vì bộ SAX là forward only cho nên chúng ta vẫn lấy dữ liệu trong quá trình xử lý – không thì dữ liệu sẽ mất hết và trong biến cố characters chúng ta sẽ kiểm tra điều kiện thỏa và bật cờ đánh dấu. Khi đó, ở biến cố EndElement chỉ được add vào trong list khi thỏa điều kiện nó là node dữ liệu, cụ thể đây là student, và giá trị tìm kiếm thỏa mãn, cụ thể ở đây đó là bằng giá trị status

    • Xử lý search trên Servlet để chuyển sang trang trình bày kết quả

    • Xử lý kết quả trên trang trình bày

    • Cấu trúc project của chúng ta hiện nay như sau

    • Mapping Servlet tìm kiếm vào ProcessServlet để hoàn tất mô hình MVC

    • Thực hiện clean and Build Project, Deploy và test chức năng search
      • Login thành công đến chức năng Search

      • Nhập giá trị để search
        • Search có kết quả

        • Search không tìm thấy

Chúc mừng quí vị đã hoàn tất và nắm được mô hình parser của SAX và cách vận dụng để ứng dụng tìm kiếm của SAX. Việc lựa chọn parser là tùy theo nghiệp vụ và nội dung xử lý của từng ứng dụng khác nhau và tùy theo đặc tính của parser

Chúng tôi hy vọng nội dung của bài này giúp ích quí vị.

Rất mong sự góp ý chân thành và chia sẻ của quí vị về vấn đề này. Hẹn gặp lại quý vị ở các chủ đề khác liên quan đến XML.

Không có nhận xét nào:

Đăng nhận xét