Thứ Tư, 31 tháng 8, 2016

Giới thiệu về DOM – định nghĩa, DOM API và cách thức sử dụng DOM API kết hợp với XPath API để khai thác dữ liệu trong tài liệu XML

Giới thiệu về DOM – định nghĩa, DOM API và cách thức sử dụng DOM API kết hợp với XPath API, JSTL - XML để khai thác dữ liệu trong tài liệu XML

Mục đích: Chủ đề của bài này giới thiệu về khái niệm liên quan đến cây DOM và sử dụng DOM API để parsing và khai thác dữ liệu trong tài liệu XML. Qua nội dung tổng quát của lý thuyết, chúng tôi sẽ thực hiện một ứng dụng sử dụng trên web nhằm để khai thác dữ liệu trong tập tin XML nhằm hiểu rõ nội dung của lý thuyết đã đề ra. Trong chủ để này, chúng tôi sẽ đề cập đến cách áp dụng Xpath API trên nền DOM API kết hợp với JSTL – XML taglib để khai thác dữ liệu XML một cách thuận lợi nhất.

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

Tổng quan DOM - Document Object Model

  • Đây là cách thức cho phép người sử dụng thao tác tài liệu XML được nạp vào bộ nhớ với cấu trúc hình cây được lưu trữ trong bộ nhớ
  • Vì tổ chức trên bộ nhớ, nên
    • Cho phép truy cập, thao tác chỉnh sửa trực tiếp trên bộ nhớ từ các ứng dụng khác nhau
    • Tuy nhiên, chỉ phù hợp áp dụng với tài liệu XML có kích thước nhỏ vì kích thước bộ nhớ giới hạn nên việc tổ chức dữ liệu hình cây có thuận tiện trong việc truy xuất nhưng không thể nạp tài liệu XML phức tạp và kích thước lớn vào trong bộ nhớ
    • Mỗi element trong tài liệu XML được tổ chức thành dạng node trong cấu trúc hình cây
    • Document object/interface là thành phần quản lý và tham chiếu đến cấu trúc cây trên bộ nhớ
    • Cấu trúc DOM của tài liệu XML được đưa vào bộ nhớ có dạng tương tự như sau

  • DOM API được định nghĩa bởi cả Microsoft và Sun để thao tác trực tiếp tài liệu XML trên HTML và trong ứng dụng sử dụng tài liệu XML. Ở đây, chúng tôi đề cập đến DOM API của Sun trong việc thao tác khai thác tài liệu XML trên ứng dụng
  • Các kiểu dữ liệu được dành cho node trong API như sau
    • Element, Node: tương ứng Element trong tài liệu XML
    • Attribute là dạng node không được thể hiện trong mô hình cây mà chúng là tập Node được lưu trong Map và là thuộc tính của Element Object được lưu tương ứng trên hình cây. Điều này có nghĩa, muốn truy cập Attribute thì phải truy cập đến Element
    • Các kiểu dữ liệu thông thường như Comment, CDATA Section, Processing Instruction, DocumentType tương ứng với các thành phần trong XML như là Comment, CDATA Section, Processing Instruction và DTD
    • Text: kiểu dành cho chữ trong tài liệu xml

    • Ngoài ra, còn có một số kiểu dữ liệu ít phổ dụng như là
      • Document Fragment: giữ một phần tài liệu XML
      • Entity, Entity Reference, Notation dành cho entity trong DTD
  • Cơ chế khi sử dụng DOM API khai thác tài liệu XML

    • Document Builder Factory được sử dụng để tạo ra bộ parser để parsing tài liệu XML đưa vào bộ nhớ, cụ thể là Document Builder object
      • Để tạo ra Document Builder Factory object, chúng ta sẽ sử dụng phương thức newInstance();
      • Từ document builder factory, chúng ta tạo ra bộ DOM Parser với phương thức newDocumentBuilder()
    • Document Builder thực hiện đón nhận tài liệu XML dưới dạng file, InputStream, Input Source, urls và thực hiện parse tài liệu để đưa vào bổ nhớ với phương thức parse
    • Trong quá trình parsing và construct nên cây DOM, mọi thao tác trên cây DOM hay vùng nhớ đang construct sẽ không hiệu lực
    • Sau khi construct cây DOM thành công, parser sẽ trả lại cho người lập trình Document Object có địa chỉ tham chiếu đến cây DOM hay vùng nhớ chứa dữ liệu
    • Người sử dụng dùng API để thao tác và truy xuất dữ liệu thông qua DOM API hay kết hợp với XPath API để khai thác dữ liệu
  • Một số phương thức phổ dụng được dùng để khai thác dữ liệu trong mô hình DOM
    • Để truy xuất node trên cây DOM (Đây là các phương thức phổ dụng của Node Interface)
      • public String getNodeName() lấy tên node của node đang duyệt
      • public String getNodeValue() throws DOMException lấy trị của một node, hàm này thường dùng lấy giá trị của node attribute bởi vì element không có chứa trị, thân của element không là trị mà chính là text node của nó
      • public String getTextContent() lấy text của node hiện hành
      • public Node getParentNode() lầy node cha của node hiện hành
      • public NameNodeMap getAttributes() lấy tập node của node hiện hành, được chứa trong map và dùng tên của attribute như là key để truy xuất giá trị của attribute
      • Các phương thức của NodeList Interface
        • public Node item(int index) lấy từng phần tử trong NodeList
        • public NodeList getChildNodes() lấy tập node con của node hiện hành
        • public NodeList getElementsByTagName(String tagName) lấy tập các element có tên đưa vào
    • Thêm một node mới vào trong cây DOM
      • Theo nguyên tắc, chúng ta sẽ dùng object DOM có sẵn để construct nên các node DOM trong bộ nhớ. Sau đó, attach chúng vào trong nhau theo mối quan hệ cấp độ để tạo thành nhánh. Cuối cùng, chúng ta mới đưa nhánh đó vào cây DOM trên bộ nhớ
      • Các phương thức cung cấp tiếp theo là của Document Interface
        • public Element createElement(String tagName) throws DOMException dùng để tạo ra một element mới
        • public Text createTextNode() tạo ra text node
        • public Comment createComment(String data) tạo comment
      • Các phương thức cung cấp của Element Interface
        • public String setAttribute (String name, String value) throws DOMException tạo attribute mới cho một element
      • Các phương thức của Node Interface
        • public Node appendChild(Node newChild) throws DOMException gán nhánh hay tạo quan hệ giữa các node với nhau
    • Remove một node ra khỏi cây DOM
      • Luôn luôn phải tìm node cần hủy. Tuy nhiên, khi đứng hay đang trỏ đến node đó không được hủy nó bởi vì sẽ làm mất vết. Chúng ta thực hiện lui lên cấp độ cha hay cha của cha nó tùy theo ý tưởng là xóa một phần hay xóa một phần tử để làm cây DOM wellformed tương ứng với tài liệu XML
      • Thực hiện truy xuất cây DOM tìm kiếm node, thực hiện tìm kiếm cha với mức level tùy theo yêu cầu
      • Gọi hàm thực thi việc tách nhánh ra khỏi cây DOM
        • public Node removeChild(Node oldChild) throws DOMException tách nhánh ra khỏi cây DOM
    • Sửa chữa giá trị trong node
      • Tương tự như việc remove node, chúng ta cũng phải thực hiện việc tìm node. Sau đó, thực hiện thay đổi giá trị tùy theo yêu cầu
      • Các phương thức cung cấp của Element Interface
        • public String setAttribute (String name, String value) throws DOMException thay đổi attribute mới cho một element
      • Các phương thức cung cấp của Node Interface
        • public void setTextContent (String content) : thay đổi giá trị text của node

Tổng quan XPath API

  • Xử lý XPath trên cây DOM đã được trên bộ nhớ để truy xuất cây DOM theo cách nhanh nhất mà không cần duyệt cây đệ qui
  • Các thành phần phương thức được cung cấp trong XPath
    • XPathFactory dùng để tạo XPath object với phương thức newInstance()
    • XPath dùng để cung cấp phương thức để truy xuất và duyệt cây DOM với phương thức
      • Object|String evaluate(String expression, InputSource doc,
        QName returnType) throws XPathExpressionException
        duyệt cây DOM và trả ra kết quả theo ý muốn
    • XPathExpression sử dụng để đón biểu thức XPath để đưa vào xử lý
    • XPathConstants  định nghĩa các hằng số áp dụng để lấy trị trả về như NODESET, NODE, STRING, NUMBER, BOOLEAN, ...
  • Nguyên lý xử dụng
    • Thực hiện parsing cây DOM như nội dung đã đề ra ở phần trên nhưng không thực hiện duyệt cây DOM
    • Tạo ra XPath object, sau đó dùng phương thức evaluate để lấy giá trị hay tập giá trị
    • Sau đó, dùng phương thức đã đề ra trong phần DOM để duyệt cây và xử lý

Xây dựng ứng dụng để truy xuất dữ liệu trong tài liệu XML

  • Mục đích của bài này chủ yếu là mô tả cách khai thác XML và áp dụng các lý thuyết đã nêu trên. Các nội dung thực hiện trong bài khi áp dụng thực tế phải tuân thủ business, không đơn giản áp dụng một một. Nếu áp dụng các nội dung một cách rập khuôn thì nó không còn mang tính thực tế cho ứng dụng

Yêu cầu

  • Nắm vững các khái niệm cơ bản về DOM, XPath API nêu trên và XPath trong các bài trước
  • Nắm vững cú pháp và kiến thức về OOP
  • 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
  • Server: Tomcat

Mô tả chức năng

  • Giao diện đầu tiên yêu cầu người dùng đăng nhập với tên account, account chỉ đăng nhập khi đúng id, đúng password và status khác dropout.
    • Nếu thỏa điều kiện, trang home xuất hiện và welcome tên full name đầy đủ của người dùng
    • Ngược lại, thông báo lỗi xuất hiện
  • Nếu đăng nhập thành công thì họ sẽ được search theo địa chỉ với giá trị gần đúng
  • Thực hiện xóa trực tiếp dữ liệu trên lưới tìm kiếm
  • Thực hiện update giá trị trên lưới, cụ thể là lớp, …
  • Thực hiện thêm một hang dữ liệu mới vào trong XML

Cấu trúc tài liệu XML được thao tác và đặt tại thư mục WEB-INF của ứng dụng  như sau

Các bước thực hiện

  • Tạo Web Application tương tư như kết hợp JavaFX với JSP và JDBC
    • Tên project: XMLSE0961
    • Server: Apache Tomcat 6.0.26 hay 7.0.34 hay 8.0.27
    • J2EE version: 1.4 hay JavaEE 5
  • Chúng ta thực hiện chức năng login trước
    • Tạo trang login.html và thiết lập trang chạy đầu tiên của ứng dụng

    • Để xử lý dữ liệu, chúng ta cần có bộ parser DOM, chúng ta tạo Java class chứa các phương thức utilities cho XML với tên là XML Utilities
      • Chúng ta tạo phương thức parseDOMFromFile, truyền vào tham số là đường dẫn file XML cần parse và trả về cho người gọi Document Object trỏ đến vùng nhớ cây DOM

    • Chúng ta thực hiện tạo ProcessServlet để thực hiện xử lý chức năng login
      • Để thực hiện parsing, với cấu trúc tài liệu chúng ta cần quan tâm xử lý theo thứ tự như sau
        • Chọn các node với tên là student để xử lý
        • Lấy thuộc tính id, so sánh với password, nếu khớp thì tiếp tục
        • Lấy tất cả tập con của node student
        • Duyệt từng thành phần nhưng chỉ quan tâm các giá trị lastname, firstname, middlename
        • Đến thành phần của password, thực hiện so sánh password, nếu không khớp thì thoát để duyệt node khác
        • Nếu khớp, thực hiện lấy status và kiểm tra khác dropout
        • Nếu khớp dừng quá trình tìm kiếm, nếu không khớp thực hiện cho đến node cuối cùng của cây DOM
      • Dựa trên phân tích nêu trên, chúng ta xây dựng hàm đệ qui với tên checkLogin, truyền vào 03 tham số String username, String password. Quan trọng nhất là Node node để cho phép chúng ta duyệt trên một nhánh cây bất kỳ

      • Sau khi có hàm đệ qui, chúng ta thực hiện xử lý trên servlet và trả kết quả về cho người dùng theo thứ tự parsing DOM từ tài liệu XML, goi xử lý checking login và trình bày kết quả ra màn hình tùy theo kết quả

    • Chúng ta tạo trạng invalid.html và search.jsp để hoàn tất tác vụ

 

    • Cấu trúc ứng dụng web đến hết tác vụ này như sau

    • Chúng ta thực hiện clean and build, sau đó deploy và thực thi ứng dụng như sau
      • 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 đã hoàn tất chức năng login, chúng ta tiếp tục thực hiện với chức năng search tìm kiếm tất cả các sinh viên bất kể trạng thái và trình bày dữ liệu ra lưới
    • Trong phần chức năng này, chúng ta sẽ áp dụng XPath API trên cây DOM parse sẵn để tìm kiếm và truy vấn dữ liệu nhanh hơn
    • Bổ sung Xpath function trong XMLUtilities

    • Chúng ta muốn tìm gần đúng giá trị của address, chúng ta thực hiện áp dụng plugin trong bài XPath để tìm ra được chuỗi xpath truy vấn như sau

//student[contains(address, '" + giá trị cần truy vấn + "')]

    • Chúng ta thực hiện bổ sung vào trong ProcessServlet, cụ thể
      • Thực hiện parsing DOM
      • Tạo Xpath Object, truy vấn dữ liệu với biểu thức để trả về tập NodeList
      • Duyệt tập node list trả về nạp vào object để chuyển sang trang trình bày dữ liệu dưới dạng lưới
    • Thực hiện tạo ra object đại diện cho từng record của student, cụ thể chúng ta tạo class StudentDTO chứa các thuộc tính mapping với dữ liệu trong tài liệu XML

    • Thực hiện bổ sung code Search cho ProcessServlet cho xử lý lấy chức năng Search

      • Ngoài cách duyệt for khi có một node sau khi sử dụng XPath, tại phần lấy được tập node con của node Student, chúng ta có thể sử dụng XPath để truy vấn trên node hiện hành để lấy thông tin trực tiếp mà không cần phải duyệt for và xét điều kiện if. Trong nội dung này cần lưu ý, việc lấy xpath của một node hiện hành sẽ thực hiện như cách thức áp dụng của XSLT engine là chỉ cần gõ tên phần tử con mà không cần phải có // như mệnh đề XPath khác. Ngoài ra, trong phần nội dung code, chúng ta có thể tối ưu bằng cách thay vì parse DOM nhiều lần, chúng ta sẽ lưu trữ DOM trên session và tận dụng lại ở tất cả các chỗ khác để tiết kiệm tài nguyên và tăng hiệu suất khi truy cập
        • Lưu trữ DOM vào session tại LoginServlet

        • Tối ưu SearchServlet

    • Chúng ta có thể tối ưu hơn nữa khi xây dựng hàm lấy dữ liệu của một node hay một attribute trong cây DOM như sau

      • Cập nhật Search Servlet như sau

    • Chúng ta thực hiện trình bày giao diện trên trang home với dữ liệu từ ProcessServlet chuyển qua
      • Add thư viện JSTL 1.1 vào trong library của Project
      • Bổ sung code vào trong trang search.jsp với import taglib và xử lý trình bày

      • Chúng ta hoàn tất chức năng Search. Cấu trúc project hiện nay như sau

      • Thực hiện clean and build, deploy, và run ứng dụng cho đến form search

 

    • Ngoài ra, chúng ta có thể xử lý kết hợp với taglib XML của JSTL để duyệt dữ liệu theo mô hình Single Pipeline mà không cần thông qua DTO
    • Cập nhật Search Servlet theo tiêu chí tạo thành List các Node sau khi truy vấn bằng XPath

    • Chuyển qua trang search.jsp để thực hiện duyệt kết hợp với object List của Java và dung xml taglib để duyệt từng phần tử của Node trong List

    • Kết quả thực thi khá tốt và khá nhanh tiết kiệm thời gian xử lý
  • Chúng tiếp tục thực hiện chức năng Delete trên lưới đối với từng hàng dữ liệu
    • Chúng ta sẽ gửi ID về server để thực hiện yêu cầu xóa
    • Thực hiện tìm kiếm student thỏa điều kiện với id
    • Không được phép hủy node chúng ta đang trỏ tới vì sẽ mất vị trí vùng nhớ
    • Thực hiện tìm cha của node thỏa điều kiện
    • Remove nhánh con ra khỏi cha
    • Tranform DOM trở thành file để lưu trữ
  • Chúng ta bổ sung thêm link Delete trong trang home.jsp, sử dụng kỹ thuật URL Rewriting

  • Để thực hiện quá trình transform từ cây DOM thành file, chúng ta bổ sung thêm phương thức cho class XMLUtilities

  • Thực hiện bổ sung code xử lý chức năng Delete vào trong ProcessServlet
    • Parsing DOM
    • Sử dụng XPath để tìm node student với id thỏa điều kiện
    • Tìm cha của node student
    • Cắt nhánh ra khỏi cây DOM trên bộ nhớ
    • Transform DOM Source thành Stream File
    • Chuyển trang về home thực hiện tự động Search lại để cập nhật lại trang sau khi delete

    • Thực hiện clean and build, deploy và run đến chức năng search

 

    • Lưu ý: khi delete, giá trị file XML trong WEB-INF của project sẽ không bị ảnh hưởng mà chỉ có tập tin trong WEB-INF tại thư mục build mới ảnh hưởng

    • Chúng ta đã hoàn tất chức năng Delete
  • Chúng ta tiếp tục thực hiện chức năng Update với 04 field Password, Status, Class, và Sex
    • Cơ chế thực hiện tương tự như Delete, đó là, tìm student thỏa id
    • Thực hiện thay đổi các giá trị
    • Transform DOM thành file
  • Chúng ta thực hiện cập nhật thay đổi trang search.jsp với kỹ thuật hidden form field (đã trình bày nội dung này ngay trong phần search ở phía trên)
    • Chúng ta thực bổ sung code trong ProcessServlet
      • Parsing DOM
      • Dùng XPath để xác định student thỏa id
      • Thay đổi giá trị của thuộc tính và text của element
      • Transform DOM thành file

      • Thực hiện clean and build, deploy, và run đến chức năng search

      • Cập nhật giá trị và nhấn update ở dòng số 2

      • Tập tin xml được cập nhật

      • Chúng ta đã hoàn tất chức năng Update
  • Chúng ta tiếp tục thực hiện chức năng cuối cùng, đó là, chức năng insert hay thêm mới nội dung node vào cây DOM
    • Cho phép đăng ký account mới
    • Dựa trên Document object để tạo hay construct các node rời rạc trong bộ nhớ
    • Tạo mối quan hệ giữa các node theo chuẩn tài liệu xml welform và validate để tạo thành nhánh cây
    • Tìm node trên cây DOM mà chúng ta sẽ chèn nhánh vừa tạo xong vào
    • Tạo mối quan hệ giữa chúng
    • Thực hiện transform DOM trở thành file
  • Chúng ta thực hiện bổ sung liên kết đăng ký vào trang login.html

  • Tạo trang createNewAccount.html

  • Bổ sung thêm 02 method để tạo Element và tạo Attribute trong XMLUtilities

  • Thực hiện bổ sung code trong ProcessServlet cho việc xử lý thêm mới

    • Cấu trúc project đến lúc này như sau

    • Thực hiện clean and build, deploy và chạy ứng dụng

      • Click link Register và nhập các giá trị, click Register

 

      • Tập tin xml được cập nhật như sau

      • Chúng ta đã hoàn tất chức năng cuối cùng là insert để hoàn tất toàn bộ mọi thao tác trên cây DOM

 

Chúc mừng các bạn đã hoàn tất và nắm các khái niệm về sử dụng DOM và ứng dụng chúng vào bài cụ thể trong việc khai thác dữ liệu. Chúng ta sẽ áp dụng nó trong các nội dung tiếp theo của chủ đề liên quan đến khái niệm và sử dụng XML kết hợp với API của ngôn ngữ lập trình và làm tăng tính hiệu quả trong xử lý XML và đưa dữ liệu cho chương trình

Chúng tôi hy vọng nội dung của bài này giúp ích các bạn trong việc cài đặt  và áp dụng DOM trong các ứng dụng.

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