openplanning

Phân tích XML bằng cách sử dụng mô hình DOM trong Java

  1. Giới thiệu
  2. Tính năng và các đặc điểm mô hình DOM
  3. Nút cây DOM và các kiểu nút (Node)
  4. Mô hình DOM trong Java
  5. DOM Programing

I am writting this document.

Ready Vietnamese Version.

ENGLISH VERSION
... COMMING SOON!

1. Giới thiệu

2. Tính năng và các đặc điểm mô hình DOM

Lịch sử của DOM
  • DOM là một tiêu chuẩn được định nghĩa bởi tổ chức W3C, cũng giống như XML
  • DOM không được thiết kế một cách cụ thể cho công nghệ java (không giống với SAX)
  • DOM dùng cho mọi nền tảng(cross-platform) và mọi ngôn ngữ (crosslanguage)
    • Uses OMG's IDL to define interfaces
    • IDL to language binding
DOM là một tiêu chuẩn do một tổ chức W3C định nghĩa và mang tính quốc tế tất cả các ngôn ngữ tôn trọng các định nghĩa này và xây dựng các API dựa theo các tiêu chuẩn đó.Thực tế thì có rất nhiều ngôn ngữ như C++,C#,...đều hỗ trợ mô hình DOM .Do đó DOM không phải thiết kế dành riêng cho Java ,tuy nhiên nếu nói về các API cho phép phân tích các tài liệu XML thì chúng ta còn có mô hình SAX(Simple API for XML) một mô hình phân tích XML đơn giản hơn DOM rất nhiều ban đầu thiết kế cho Java nhưng hiện nay các ngôn ngữ khác cũng đã bắt đầu hỗ trợ mô hình này .....
Các đặc điểm của mô hình DOM
  • Truy cập tài liệu XML như là một cấu trúc cây
  • Được bao gồm hầu hết các nút element và các nút text
  • Có thể "rà xoát" (Traversing) cây từ sau ra trước
  • Đòi hỏi bộ nhớ lớn hơn
    • Khá nặng nề trong việc tải và lưu trữ
  • Sử dụng nó khi rà xoát và hiệu chỉnh cây
Với một tài liệu XML mô hình DOM sẽ duyệt và chuyển nó thành một mô hình cây của các Object .Ví dụ một element tương ứng với một Object element , một thuộc tính tương ứng với một Object thuộc tính các Object này được tạo ra trong bộ nhớ (memory) và có cấu trúc cây .Chính vì vậy mà có thể rà xoát tài liệu XML này bằng cách rà xoát trên các Object trong bộ nhớ .Và có thể thêm bớt các thông tin,object để tạo ra một tài liệu XML mới hoặc một sản phẩm mới ,..
Hành động của DOM
Hình minh họa dưới cho bạn thấy đầu vào là một tài liệu XML được bộ phân tích bởi mô hình DOM và một sẽ cây được tạo ra trong bộ nhớ mang thông tin của tài liệu đó .Việc phân tích tài liệu XML bây giờ đưa về phân tích ,sử lý các nút của cây.

3. Nút cây DOM và các kiểu nút (Node)

  • Tài liệu XML được hình dung như là một cây
  • Một cây được làm từ các nút cây(nodes)
  • Có 12 kiểu nút cây khác nhau
  • Các nút cây có thể chứa các nút cây khác(Phụ thuộc vào kiểu nút cây là gì)
    • Nút cha gồm có các nút con
Có 12 kiểu Node:
  • Document (Mô tả một nút lớn nhất đó là toàn bộ tài liệu XML)
  • DocumentFragment (Một đoạn tài liệu XML)
  • Element
  • Attr (Nút thuộc tính)
  • Text (Nút chứa text)
  • Comment (Ghi chú trong tài liệu XML)
  • ProcessingInstruction (Tương ứng với chỉ lệnh trong XML)
  • DocumentType (Định nghĩa XML)
  • Entity (Tương ứng với thực thể trong XML )
  • EntityReference (Tương ứng với các thực thể tham chiếu trong XML)
  • CDATASection (Tương ứng với các phân đoạn trong XML)
  • Notation (Tương ứng với các chú thích NOTATION trong XML)
Phân cấp cây DOM
  • Một nút Document bao gồm.
    • Một nút Element (Đây chính là Element gốc của tài liệu)
    • Một hoặc nhiều các nút chỉ lệnh (ProcessingInstruction)
    • Một hoặc nhiều nút Comment
..
  • Một nút Element có thể chứa
    • Các nút Element khác
    • Một hoặc nhiều nút Text
    • Một hoặc nhiều nút thuộc tính (Attr)
    • Một nút thuộc tính (Attr) chứa
  • Một nút Text
(Xem hình minh họa trong các trường hợp cụ thể để thấy được bức tranh chi tiết)
Các list ở trên cho bạn thấy một bức tranh sơ lược và nó thực sự là không đầy đủ về các nút cây DOM thì chứa những gì .Trong các trang tiếp theo theo dòng tìm hiểu chúng ta sẽ thấy rõ được một cách đầy đủ hơn .
Ví dụ trong khái niệm XML chúng ta biết ví dụ một thuộc tính bao gồm tên và giá trị của nó :
<name firstName="Nguyen" lastName="Van" />
Với trích đoạn XML trên rõ ràng một nút thuộc tính chứa một nút Text .Tuy nhiên trong ví dụ sau nếu đứng trên khía cạnh XML thuần thúy thì lại thấy nó có thể chứa một nút khác nữa đó là EntityReference :
<film name="tom &amp; jerry"/>
Ở đây ta có một thực thể tham chiếu &amp; nó tương ứng với dấu & .Trong mô hình DOM các thực thể tham chiếu thường bị chuyển thành text mà nó chứa .Và vì vậy mà thông thường thì một nút thuộc tính (Attr) chỉ có một nút con là nút Text thôi .Đây là một trong các chú ý .Xong bạn hỏi vậy trong mô hình DOM đưa nút EntityRefference vào có ý nghĩa gì ? Vấn đề này là cần thiết khi bạn muốn thêm một thực thể tham chiếu vào là một con của một nút nào đó.Có nhiều vấn đề khác sẽ được dần dần trình bầy.
Một ví dụ đơn giản
<?xml version="1.0"?>
<people>
  <person born="1912">
       <name>
         <first_name>Alan</first_name>
         <last_name>Turing</last_name>
       </name>
       <profession>computer scientist</profession>
  </person>
</people>
Và đây là mô hình cây DOM:

4. Mô hình DOM trong Java

Thực tế là W3C đã đưa ra danh sách 12 interface mô tả các nút của cây DOM .Mỗi interface có ra danh sách các hàm ,các thuộc tính để can thiệp,sử dụng .
(Khi bạn làm việc với DOM trên một ngôn ngữ nào đó khác Java thì cũng phải làm việc với các interface có các thuộc tính, method tương tự đó chính là cái hay của DOM - một mô hình có tính thống nhất hành động giữa các ngôn ngữ).
Các interface này có một phân cấp rõ ràng .
Ví dụ:
  • interface org.w3c.dom.Element mô tả một nút Element
  • interface org.w3c.dom.Attr mô tả một nút thuộc tính .
Tất cả trực tiếp hoặc không trực tiếp đều mở rộng từ interface org.w3c.dom.Node.
Phân cấp các interface (Các interface trong package org.w3c.dom)
  • Node
    • Document
    • DocumentFragment
    • DocumentType
    • ProcessingInstruction
    • CharacterData
      • Comment
      • Text
        • CDATASection
    • Element
    • Attr
    • EntityReference
    • Entity
    • Notation
Các interface khác cho DOM
  • NodeList
  • NamedNodeMap
  • DOMImplementation
Ba interface nằm trong bó org.w3c.dom khá quan trọng
  • NodeList là một interface mô tả một tập hợp một số nút con của một nút nào đó.Method getChildNodes( ) của interface Node sẽ trả về một đối tượng NodeList chính là danh sách các nút con của nút gọi method này .
  • Với một nút Element gọi method này sẽ trả về NodeList - một tập hợp trìu tượng chứa các nút con của Element trên.Xong trong NodeList này lại không có các thuộc tính của Element (đây là lý do tại sao mà ta nói trong mô hình DOM thuộc tính không được coi là con của Element) .Nút Element gọi method getAttributes( ) sẽ trả về đối tượng NamedNodeMap một danh sách trìu tượng chứa các thuộc tính của Element.
  • NamedNodeMap còn có chứa các Entity mà ta sẽ thấy khi gọi method getEntities( ) của đối tượng DocumentType chẳng hạn .Ok tất cả chi tiết trong phần sau.
Node interface
  • Là kiểu dữ liệu chính trong DOM
  • Mô tả một nút trong cây DOM
  • Tất cả các nút đều là kiểu interface Node
    • Từ việc tất cả các kiểu nút đều là kiểu interface Node, tất cả các nút có thể xử lý trong một cách khá tương tự nhau
Một số method của Node trong Java:
public short getNodeType();
public String getNodeName( );
public String getNodeValue( );
public NamedNodeMap getAttributes();
public NodeList getChildNodes( );
Không phải tất cả các method thấy trên đều có ý nghĩa cho một kiểu nút cụ thể ví dụ với Comment thừa kế từ Node --> có method getAttributes() xong Comment thì làm gì có thuộc tính (thật vô nghĩa)
Bảng dưới đây mô tả cho bạn một cái nhìn tổng quan hơn về việc ý nghĩa của các method trên trong các trường hợp cụ thể.
Interface
getNodeName()
getNodeValue()
getAttributes()
getChildNodes()
Attr
Tên của thuộc tính
Attribute Name
Giá trị của thuộc tính
Attribute Value
null
NodeList
CDATASection
"#cdata-section"
Nội dung của CDATA Section
Content of CDATA Section
null
NodeList
(Rỗng)
(Empty)
Comment
"#comment"
Nội dung của comment
Content of Comment
null
NodeList
(Rỗng)
(Empty)
Document
"#document"
null
null
NodeList
DocumentFragment
"#document-fragment"
null
null
NodeList
DocumentType
Tên của document type
Document Type Name
null
null
NodeList
(Rỗng)
(Empty)
Element
Tên của thẻ
Element name
null
NamedNodeMap
NodeList
Entity
Tên của entity
Entity Name
null
null
NodeList
EntityReference
Tên của entity được tham chiếu
Entity Reference name
null
null
NodeList
Notation
Tên của Notation
Notation name
null
null
NodeList
(Rỗng)
(Empty)
ProcessingInstruction
target
Toàn bộ text sau tên của mục tiêu
Text of Processing Instruction
null
NodeList
(Rỗng)
(Empty)
Text
"#text"
Nội dung của nút text
Text content.
null
NodeList
(Rỗng)
(Empty)
Method getNodeType() trong interface Node trả về giá trị là kiểu Short định nghĩa bởi các hằng số trong interface này:
// NodeTypes
 public static final short ELEMENT_NODE = 1;
 public static final short ATTRIBUTE_NODE = 2;
 public static final short TEXT_NODE = 3;
 public static final short CDATA_SECTION_NODE = 4;
 public static final short ENTITY_REFERENCE_NODE = 5;
 public static final short ENTITY_NODE = 6;
 public static final short PROCESSING_INSTRUCTION_NODE = 7;
 public static final short COMMENT_NODE = 8;
 public static final short DOCUMENT_NODE = 9;
 public static final short DOCUMENT_TYPE_NODE = 10;
 public static final short DOCUMENT_FRAGMENT_NODE = 11;
 public static final short NOTATION_NODE = 12;
Các method thông dụng:
public String getNodeName();
public String getNodeValue() throws DOMException;
public void setNodeValue(String nodeValue) throws DOMException;
public short getNodeType ();
public Node getParentNode();
public NodeList getChildNodes();
public Node getFirstChild();
public Node getLastChild();
public Node getPreviousSibling();
public Node getNextSibling();
public NamedNodeMap getAttributes();
public Document getOwnerDocument( ) ;
Interface Node (Một số method có thể thao tác sửa đổi nút trên cây DOM)
public Node insertBefore (Node newChild , Node refChild)throws DOMException ;
 public Node replaceChild(Node newChild, Node oldChild)throws DOMException ;
 public Node removeChild(Node oldChild) throws DOMException;
 public Node appendChild(Node newChild ) throws DOMException;
 public boolean hasChildNodes ();
 public Node cloneNode(boolean deep);
 public void normalize();
 public boolean supports(String feature, String version);
 public String getNamespaceURI ();
 public String getPrefix ();
 public void setPrefix (String prefix) throws DOMException;
 public String getLocalName ();
NodeList,NamedNodeMap interface
Document interface
  • Mô tả toàn bộ tài liệu XML
  • Các nút con của Document:
    • Duy nhất một kiểu nút Element (Gốc của tài liệu XML)
    • DocumentType (Nếu có thì là 1)
    • ProcessingInstruction (0 hoặc nhiều)
    • Comment (0 hoặc nhiều)
public interface Document extends Node {
    Attr createAttrbute(String name);

    Attr createAttributeNS(String namespaceURI, String qName);

    CDATASection createCDATASection(String data);

    Comment createComment(String data);

    DocumentFragment createDocumentFragment();

    Element createElement(String tagName);

    Element createElementNS(String namespaceURI, String qName);

    EntityReference createEntityReference(String name);

    ProcessingInstruction createProcessingInstruction(String target, String data);

    Text createTextNode(String data);

    DocumentType getDocType();

    Element getDocumentElement();

    Element getElementById(String elementId);

    NodeList getElementsByTagName(String tagName);

    NodeList getElementsByTagNameNS(String namespaceURI, String localName);

    DOMImplementation getImplementation();

    Node importNode(Node importNode, boolean deep);
}
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

....

// Tạo một đối tượng DocumentBuilderFactory từ method tĩnh của nó
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();


// Sét đặt việc kiểm tra tính hợp lệ của tài liệu sẽ phân tích sau này.
factory.setValidating(true);

// Tạo đối tượng DocumentBuilder
DocumentBuilder builder = factory.newDocumentBuilder();

/*
 * Tạo một đối tượng Document từ đối tượng builder bằng cách phân tích
 * một URL xml. Chúng ta cũng có thể phân tích từ InputStreams, Files,
 * và nguồn đầu vào SAX
 */
 Document doc = builder.parse("http://foo.com/bar.xml");
Ví dụ:
xmlFile.xml
<?xml version="1.0" ?>

<rootOfXml>
 This is text 01
 <MyElement1>Text of MyElement1</MyElement1>
 <!--This is my Comment -->
 This is text 02
 <?myTarget01 This is My ProcessingInstruction ?>
</rootOfXml>
BeginDOMDemo.java
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

public class BeginDOMDemo {

   private void parseNow() throws ParserConfigurationException, SAXException,
           IOException {
       // Tạo một đối tượng DocumentBuilderFactory từ method tĩnh của nó
       DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

       // Sét đặt việc kiểm tra tính hợp lệ của tài liệu sẽ phân tích sau này.
       factory.setValidating(true);

       // Tạo đối tượng DocumentBuilder
       DocumentBuilder builder = factory.newDocumentBuilder();

       // Lay ra nut Document (mo ta toan bo tai lieu xml cua file xmlFile.xml
       Document xmlDoc = builder.parse("xmlFile.xml");
       // Tu nut Document xmlDoc co the lay ra phan tu goc cua tai lieu XML
       Element root = (Element) xmlDoc.getDocumentElement();
       // In ra man hinh ten cua phan tu goc cua tai lieu XML xmlFile.xml la gi
       System.out.println("Root name:" + root.getNodeName());
   }

   public static void main(String[] args) {
       BeginDOMDemo f = new BeginDOMDemo();
       try {
           f.parseNow();
       } catch (ParserConfigurationException e) {
           e.printStackTrace();
       } catch (SAXException e) {
           e.printStackTrace();
       } catch (IOException e) {
           e.printStackTrace();
       }
   }
}
Element interface
Element
public interface Element extends Node {
   public String getTagName();

   public String getAttribute(String name);

   public void setAttribute(String name, String value) throws DOMException;

   public void removeAttribute(String name) throws DOMException;

   public Attr getAttributeNode(String name);

   public Attr setAttributeNode(Attr newAttr) throws DOMException;

   public Attr removeAttributeNode(Attr oldAttr) throws DOMException;

   public NodeList getElementsByTagName(String name);

   public String getAttributeNS(String namespaceURI, String localName);

   public void setAttributeNS(String namespaceURI, String qualifiedName,
           String value) throws DOMException;

   public void removeAttributeNS(String namespaceURI, String localName)
           throws DOMException;

   public Attr getAttributeNodeNS(String namespaceURI, String localName);

   public Attr setAttributeNodeNS(Attr newAttr) throws DOMException;

   public NodeList getElementsByTagNameNS(String namespaceURI, String localName);
}
  • Mô tả một phần tử element
    • Bao gồm thẻ đóng ,thẻ mở,và nội dung
  • Các kiểu nút con:
    • Các nút Element
    • Các nút thuộc tính (Attr)
      • Chú ý thông thường thì Attr lại không được coi là con của Element vì sao ?
    • Các nút ProcessingInstruction
    • Các nút Comment
    • Các nút Text
    • Các nút CDATASection
    • Các nút EntityReference
Những Node nào là cha của Element?

Element có thể xuất hiện như là một nút con của nhiều kiểu nút .Dấu hoa thị giữa Document và Element chỉ ra rằng khi một nút Element là nút con của nút Document thì nút Element đó chính là phần tử gốc của tài liệu XML và nút Document thì chỉ có duy nhất một nút kiểu Element chính là nút gốc đó.
Ví dụ:
<?xml version="1.0" ?>

<rootOfXml myAttr01="Abc" myAttr02="What is this?">
  This is text 01
  <MyElement1>What is this ?</MyElement1>
  <!--This is my Comment -->
  This is text 02
  <?myTarget01 This is My ProcessingInstruction ?>
</rootOfXml>
/**
 * Vi du don gian bat dau voi mo hinh DOM (theo phong cach xerces
 * thuc ra phong cach xerces chi la dung class DOMParser nam trong bo
 * org.apache.xerces.parsers de phan tich tai lieu xml)
 * Trong vi du nay demo viec su dung method getAtributes() de lay ra danh
 * sach cac thuoc tinh cua Element cu the vi du nay la tap hop cac thuoc tinh
 * cua phan tu goc.
 */

import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.xml.sax.SAXException;

public class BeginAttrDemo {

    /**
     * Method nay lam nhiem vu tao ra mot bo phan tich va phan tich mot tai lieu
     * xml co ten la xmlFile.xml  
     */
    private void parseNow() throws ParserConfigurationException, SAXException, IOException {

        // Tạo một đối tượng DocumentBuilderFactory từ method tĩnh của nó
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        // Sét đặt việc kiểm tra tính hợp lệ của tài liệu sẽ phân tích sau này.
        factory.setValidating(true);

        // Tạo đối tượng DocumentBuilder
        DocumentBuilder builder = factory.newDocumentBuilder();

        // Lay ra nut Document (mo ta toan bo tai lieu xml cua file xmlFile.xml
        Document xmlDoc = builder.parse("xmlFile.xml");

        // Tu nut Document xmlDoc co the lay ra phan tu goc cua tai lieu XML
        org.w3c.dom.Element root = (Element) xmlDoc.getDocumentElement();
        // In ra man hinh ten cua phan tu goc cua tai lieu XML xmlFile.xml la gi
        System.out.println("Root name:" + root.getNodeName());
        NamedNodeMap nodeMap = root.getAttributes();
        for (int i = 0; i < nodeMap.getLength(); i++) {
            // Lay ra phan tu thu i trong tap hop
            Attr at = (Attr) nodeMap.item(i);
            System.out.println("Name:" + at.getName() + " Value:"
                    + at.getValue());
        }
    }

    /** Ham main */
    public static void main(String[] args) {
        BeginAttrDemo f = new BeginAttrDemo();
        try {
            f.parseNow();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
Ví dụ để phân biệt các loại Node khác nhau:
/**
 * Mot vi du trong do co su dung method myNode.getChildNodes() de lay ra mot
 * danh sach cac nut con cua mot nut nao do .Trong danh sach nay gom nhieu
 * kieu nut khac nhau myNode.getNodeType() co the cho ta nhan biet duoc cac nut nay
 * la kieu nut gi va su ly trong cac tinh huong cu the .  
 */

import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class NodeTypeDemo {

    /**
     * Method nay lam nhiem vu tao ra mot bo phan tich va phan tich mot tai lieu
     * xml co ten la xmlFile.xml
     */
    private void parseNow() throws ParserConfigurationException, SAXException,
            IOException {

        // Tạo một đối tượng DocumentBuilderFactory từ method tĩnh của nó
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        // Sét đặt việc kiểm tra tính hợp lệ của tài liệu sẽ phân tích sau này.
        factory.setValidating(true);

        // Tạo đối tượng DocumentBuilder
        DocumentBuilder builder = factory.newDocumentBuilder();

        // Lay ra nut Document (mo ta toan bo tai lieu xml cua file xmlFile.xml
        Document xmlDoc = builder.parse("xmlFile.xml");

        // Tu nut Document xmlDoc co the lay ra phan tu goc cua tai lieu XML
        Element root = (Element) xmlDoc.getDocumentElement();
        /**
         * Vi du nay khong phai la mot mau muc vi no bo qua viec su ly nhieu cac
         * kieu nut vi du co nhieu nut la con cua Document nhung khong phai la
         * con cua phan tu goc ...Vi du nay khong nhac den
         */
        processNode(root);
    }

    /**
     * Su ly cho nut Element nao do lay ra danh sach cac nut con cua no ,xem cac
     * nut con cua no la kieu gi va in ra thong tin vi du :gap nut Text in ra
     * Text:value.. gap nut CDATASection in ra CDATASection:value... danh sach
     * cac thuoc tinh cua no... gap nut con kieu Element lap lai vong lap boi
     * chinh method nay
     */
    private void processNode(Element element) {
        /**
         * In ra ten cua nut bang myNode.getNodeName() .Voi element ta co the
         * thay boi myElement.getTagName() cung co duoc ket qua tuong tu .Trong
         * tinh huong muon dieu khien viec in ra cac tiep dau ngu (prefix) nen
         * su dung cac method cung cap boi interface Element.
         */
        print("<" + element.getNodeName());
        // Lay ra danh sach cac thuoc tinh cua Element element
        NamedNodeMap nodeMap = element.getAttributes();
        for (int i = 0; i < nodeMap.getLength(); i++) {
            // Lay ra nut thu i trong tap hop
            Attr at = (Attr) nodeMap.item(i);
            print(" " + at.getNodeName() + "=\"" + at.getNodeValue() + "\"");
        }
        print(">");
        // Lay ra danh sach cac nut con cua nut Element element
        NodeList nodeList = element.getChildNodes();
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            short type = node.getNodeType();
            switch (type) {
            // Truong hop nut con thu i la mot Element
            case Node.ELEMENT_NODE:
                processNode((Element) node);// goi method nay cho Element
                break;
            case Node.COMMENT_NODE:
                print("<!-- " + node.getNodeValue() + " -->");
                break;
            default:
                /**
                 * Trong cac truong hop nut con la mot kieu nut khac .... De don
                 * gian trong vi du nay khong demo cac truong hop do .Tuy nhien
                 * se co mot vi du demo ve viec su ly toan bo cac kieu nut trong
                 * tai lieu xml .
                 */
                print("Other node.....");
                break;
            }
        }
    }

    /** Su dung trong method processNode(...) */
    private void print(String s) {
        System.out.println(s);
    }

    /** Ham main */
    public static void main(String[] args) {
        NodeTypeDemo f = new NodeTypeDemo();
        try {
            f.parseNow();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
CharacterData interface
  • Mô tả cho text
  • Là interface cha của các interface
    • Text interface
    • Comment interface
public interface CharacterData extends Node {
    public String getData() throws DOMException;

    public void setData(String data) throws DOMException;

    public int getLength();

    public String substringData(int offset, int count) throws DOMException;

    public void appendData(String arg) throws DOMException;

    public void insertData(int offset, String arg) throws DOMException;

    public void deleteData(int offset, int count) throws DOMException;

    public void replaceData(int offset, int count, String arg)
            throws DOMException;
}
Text interface
  • Mô tả nội dung nguyên văn của một element hoặc một thuộc tính
  • Chỉ chứa dữ liệu thuần text, không có đánh dấu (markup)
  • A text node for each contiguous run of pure text
    • Một Element không có Element con nào :
      • Text được mô tả trong một đối tượng Text duy nhất
    • Element có các Element con :
      • Có nhiều đối tượng Text
Một nút text có thể phân chia ra làm 2 nút text khác nhau vì một mục đích nào đó ví dụ phân chia ra làm 2 nút text sau đó trèn vào giữa một nút nào đó .Method splitText(offset) có thể phân chia nút text ra làm 2 nút text được lưu trên cây DOM và trả về nút Text thứ 2.
Text
public interface Text extends CharacterData {
   public Text splitText(int offset) throws DOMException;
}
Element myElement có một nút Element con childElement .Trong trường hợp này nó có 2 nút Text con .Nút text ở vị trí số (1) rỗng không có giá trị .
Nút Text không có một nút con nào
Xong có nhiều kiểu nút có thể có con là nút Text
Comment interface
Comment
public interface Comment extends CharacterData {
}
  • Mô tả một lời chú thích
  • Các kiểu nút con:
    • Không có
  • Node interface methods
    • getNodeValue() trả về giá trị của nút dưới dạng text.
Một Comment không có một nút con nào
Một Comment không có một nút con nào tuy nhiên có nhiều nút có thể có nút con là Comment.
CDATASection interface
CDATASection
public interface CDATASection extends Text {
}
  • Mô tả một phân đoạn CDATA
  • Các kiểu nút con
    • Không có
  • Node interface methods
    • getNodeValue() returns text
CDATASection không có kiểu nút con nào.
CDATASection không có kiểu nút con nào nhưng có nhiều kiểu nút có thể nhận CDATASection là một nút con.
Ví dụ:
case Node.TEXT_NODE:
       case Node.CDATA_SECTION_NODE:
       case Node.COMMENT_NODE:
       System.out.println(node.getNodeValue());
       break;
} // end switch statement
Attr interface
Attr
public interface Attr extends Node {
   public String getName();

   public boolean getSpecified();

   public String getValue();

   public void setValue(String value) throws DOMException;

   public Element getOwnerElement();
}
  • Mô tả một thuộc tính
  • Các kiểu nút con
    • Text nodes
    • EntityReference nodes
  • Node interface methods
    • getNodeName() trả về tên của thuộc tính
    • getNodeValue() trả về giá trị của thuộc tính.
Attr có thể có 2 kiểu nút con Text và EntityReference tuy nhiên thông thường một EntityReference thường bị phân tích thành giá trị mà nó tham chiếu tới và sát nhập vào với nút Text vì vậy chúng ta không thể có được EntityReference trong NodeList nhận được.Tuy nhiên nó có ý nghĩa trong trường hợp bạn tạo ra một nút EntityReference và có thể add nó làm con của nút Attr.
Để có thể hiểu được bạn có thể xem ví dụ:
??????????????????????????????????????????????????????????????
(JHelp-example:SeeEntityReference) ??
Không có một kiểu nút nào gọi method getChildNodes() mà nhận được một nút con là nút Attr .Với Element có thể nhận được tập hợp các thuộc tính của nó qua method getAttributes()
DocumentType interface
DocumentType
public interface DocumentType extends Node {
   
   public String getName();

   public NamedNodeMap getEntities();

   public NamedNodeMap getNotations();

   public String getPublicId();

   public String getSystemId();

   public String getInternalSubset();
}
  • Mô tả định nghĩa kiểu tài liệu
  • Các nút con
    • Không có nút con (theo nghĩa getChildNode())
  • Có thể chứa các nút Entity,Notation
Như đã nói DocumentType có thể chứa Entity,Notation nhưng thông thường 2 kiểu nút này không được coi là nút con .2 method quan trọng lấy ra các nút mà nó chứa là getEntities() và getNotations() các nút này nằm trong đối tượng NamedNodeList .
DocumentType chỉ có thể là con của Document và Document nếu có nút con DocumentType thì đó là duy nhất điều đó dễ hiểu bởi mỗi tài liệu XML chỉ có một định nghĩa kiểu tài liệu của nó.
ProcessingInstruction interface
ProcessingInstruction
public interface ProcessingInstruction extends Node {
   
   public String getTarget();

   public String getData();

   public void setData(String data) throws DOMException;
}
  • Mô tả một chỉ lệnh (processing instruction)
    • <?xml-stylesheet href ="XSL\JavaXML.html .xsl" type="text/xsl"?>(???)
    • <?myTarget value of processing instruction ?>
  • Kiểu nút con
    • Không có
  • Node interface methods
    • getNodeName() trả về mục tiêu (target)
      • Giống như method getTarget() của interface ProcessingInstruction
    • getNodeValue() trả lại phần còn lại
      • Giống như method getData() của interface ProcessingInstruction
ProcessingInstruction không có kiểu nút con nào
ProcessingInstruction không có kiểu nút con nào .Nhưng có thể là nút con của nhiều kiểu nút.
Ví dụ:
case Node.PROCESSING_INSTRUCTION_NODE:
       System.out.println("<?" + node.getNodeName() +
                          " " + node.getNodeValue() +"?>");
     break;
Entity interface
Entity
public interface Entity extends Node {
   
   public String getPublicId();

   public String getSystemId();

   public String getNotationName();
}
  • Represents an actual entity (not an entity reference)
  • Các kiểu nút con:
    • Element nodes
    • ProcessingInstruction nodes
    • Comment nodes
    • Text nodes
    • CDATASection nodes
    • EntityReference nodes
Entity không được coi là con của kiểu nút nào nhưng có thể lấy nó trong nút DocumentType qua method getEntities() của DocumentType.
EntityReference interface
EntityReference
public interface EntityReference extends Node {
}
  • Mô tả một thực thể tham chiếu
EntityReference có thể là Node con của các Node.
DocumentFragment interface
  • Mô tả một đoạn nào đó của tài liệu XML .
    • DocumentFragment không là con của một kiểu nút nào.
  • Chúng ta không thể có cách nào lấy được một đoạn tài liệu XML(DocumentFragment)từ bất kỳ một nút nào.Mặc dù ngắt một nút nào đó và con cháu của nó có thể coi là 1 đoạn tài liệu xml.DocumentFragment chỉ có ý nghĩa khi tạo ra một đối tượng này và add thêm các nút con mà DocumentFragment có thể chứa ,sau đó thì add toàn bộ DocumentFragment vào một nút nào đó.
Hình dưới đây chỉ ra rằng DocumentFragment không thể lấy được từ bất kỳ một nút nào khi gọi method getChildNodes(). Nhưng không có nghĩa một nút không thể chứa một DocumentFragment .Xem vi dụ minh họa
DocumentFragment df = document.createDocumentFragment();
// Thêm vào các nút con nào đó cho df
df.append(myNode01);
df.append(myNode02);

// Đặt nó vào một nút nào đó ví dụ một nút Element element
element.appendChild(df);
Notation interface
Notation không được coi là con của nút nào cả tuy nhiên DocumentType có thể chứa các Notation .Bạn có thể lấy từ đối tượng DocumentType ra một danh sách trìu tượng chứa các Notation thông qua method documentType.getNotations()

5. DOM Programing

Các bước sử lý DOM
  • Tạo ra một đối tượng bộ phân tích (parser object)
  • Sét đặt các tính năng(Features) và đọc các thuộc tính (Properties)
  • Phân tích tài liệu XML và nhận lấy đối tượng Document
  • Thực hiện các toán tử
    • Rà soát DOM (Traversing)
    • Vận dụng DOM(Manipulating)
    • Tạo một DOM mới
    • Viết ra đầu ra các DOM
  • Có một thực tế là trong Java có nhiều API để sử lý tài liệu XML theo mô hình DOM.
    • Bạn có thể sử dụng javax.xml.parsers, đã tích hợp sẵn vào Jdk1.5 trở lên.
    • Bạn có thể sử dụng org.apache.xerces.parsers của Apache.
  • Tạo một đối tượng bộ phân không phải là một tiêu chuẩn vì:
    • DOM không định rõ làm thế nào để tạo một đối tượng bộ phân tích.
    • Có nhiều API khác nhau ngay trong nội bộ Java, để sử lý DOM, nó tuân thủ theo tiêu chuẩn DOM, implements các interface trong org.w3c.xml.
    • Các dòng code của bạn có thể khó khăn trong việc chuyển mang (Portability)
    • Nên sử dụng JAXP (javax.xml.parsers) làm API phân tích XML theo mô hình DOM vì thư viện tích hợp sẵn trong Jdk.
Nếu bạn dùng org.apache.xerces.parsers của Apache là thư viện phân tích DOM:
import org.apache.xerces.parsers.DOMParser;
import org.w3c.dom.Document;
import org.xml.sax.SAXException ;
import java.io.IOException ;
...

String xmlFile = "C:/data/personal.xml";
DOMParser parser = new DOMParser();
try {
   //Phân tích tài liệu xml .Sau bước này có một cây DOM trong bộ nhớ
   // chính là hình ảnh của tài liệu
   parser.parse(xmlFile);
} catch (SAXException se) {
   se.printStackTrace();
} catch (IOException ioe) {
   ioe.printStackTrace();
}
//Lấy ra nút Document mô tả toàn bộ tài liệu XML
Document document = parser.getDocument();
Các toán tử thao tác trên DOM
  • Rà xoát DOM (Traversing DOM)
  • Vận dụng DOM(Manipulating DOM)
    • Nối thêm các nút (Appending nodes)
    • Xóa bỏ các nút (Removing nodes)
    • Hiệu chỉnh các nút (Modifying nodes)
  • Tạo ra một DOM mới (Generating a new DOM)
  • Serializing DOMb
  • Q: subclassing DOM?
JAXP (Java API for XML Parsing )
Ok ! Bây giờ chúng ta nói về JAXP một API cho phân tích XML nó bao gồm các API cho cả 2 mô hình SAX và DOM cung cấp bởi Sun.Trong phiên thảo luận này chúng ta không đi nói sâu về JAXP mà chỉ nói sơ lược bởi sẽ có một bài thảo luận khác dành riêng cho JAXP.
Ví dụ với JAXP/DOM
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
 
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
 
....
 
// Tạo một đối tượng DocumentBuilderFactory từ method tĩnh của nó
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 
 
// Sét đặt việc kiểm tra tính hợp lệ của tài liệu sẽ phân tích sau này.
factory.setValidating(true);
 
// Tạo đối tượng DocumentBuilder
DocumentBuilder builder = factory.newDocumentBuilder();
 
/*
 * Tạo một đối tượng Document từ đối tượng builder bằng cách phân tích
 * một URL xml. Chúng ta cũng có thể phân tích từ InputStreams, Files,
 * và nguồn đầu vào SAX
 */
 Document doc = builder.parse("http://foo.com/bar.xml");