XAUST thuộc nhóm kỹ thuật nén XML không truy vấn và phụ thuộc vào thông tin lược đồ. Bộ nén XML XAUST chuyển đổi thông tin lược đồ DTD thành một tập hợp máy tự động hữu hạn xác định Deterministic Finite Automata - DFA , mỗi phần tử trong DTD sẽ có một DFA. Mỗi transition được gán nhãn bởi một phần tử và hành động action được kết hợp với một transition được gọi đến một bộ mô phỏng simulator cho DFA của phần tử đang được gán nhãn. XAUST nhóm tất cả dữ liệu trong cùng một phần tử vào trong một
container duy nhất và sử dụng bộ nén số học số 4 arithmetic order-4 compressor để nén. Bởi vì sử dụng thông tin lược đồ DTD, XAUST có khả năng tìm, kiểm tra cấu trúc của tài liệu và có khả năng dự đoán chính xác các biểu tượng mong đợi.
Các thành phần cơ bản của XAUST bao gồm: mã hóa số học và máy tự động hữu hạn xác định.
3.3.2. Mã h a số học và mô hình ngữ cảnh hữu hạn 3.3.2.1. Mã h a số học (Arithmetic Coding)
Mã hóa số học không thay thế các kí hiệu đầu vào bằng các từ mã riêng biệt. Thay vào đó, nó xử lý luồng ký tự đầu vào và thay thế nó bằng một từ mã duy nhất ở đầu ra. Đầu ra của mã hóa số học là một số thực lớn hơn 0 và nhỏ hơn 1. Số này là duy nhất và có thể được giải mã để tạo lại chính xác luồng các kí hiệu đầu vào. Mã hóa số học bắt đầu hoạt động của nó bằng việc phân chia trong khoảng giữa 0 và 1, dựa vào sự phân bố xác suất xuất hiện của kí hiệu trong mô hình đã được xây dựng. Khoảng này sẽ được tính toán lại sau khi có một kí hiệu được mã hóa.
3.3.2.2. Mô hình ngữ cảnh hữu hạn (Finite Context Modeling)
Trong một lược đồ ngữ cảnh hữu hạn, xác suất của mỗi biểu tượng hay kí hiệu được tính toán dựa trên ngữ cảnh mà biểu tượng xuất hiện trong đó. Ngữ cảnh chỉ là những biểu tượng mà đã được xuất hiện trước đó. Mô hình là một tập hợp các bảng đếm tần suất cho mỗi ngữ cảnh. Khi gặp một biểu tượng, số đếm tần suất sẽ được cập nhật vào trong bảng. Số đếm tần suất được sử dụng để tính xác suất và lược đồ tương ứng khi mỗi biểu tượng được quét qua. Thứ tự của mô hình tham chiếu đến số lượng các biểu tượng đã xuất hiện trước đó và tạo lên một ngữ cảnh. Trong một mô hình có thứ tự k, cả hai bộ nén và bộ giải nén đều bắt đầu cùng với một mô hình. Bộ nén mã hóa biểu tượng với một mô hình đã tồn tại và sau đó cập nhật lại mô hình cho mô hình mới. Bộ giải nén tương tự giải mã một biểu tượng bằng cách sử dụng mô hình đã có và sau đó cũng cập nhật lại mô hình. Ta thấy rằng, quá trình cập nhập lại mô hình và lưu các bảng đếm tần suất là một quá trình tốn kém, tiêu tốn một số lượng lớn không gian bộ nhớ. Điều này làm cho mã hóa số học chậm hơn các lược đồ dựa trên từ điển như Ziv-Lempel.
3.3.3. Máy tự động hữu hạn xác định
Hình 3.4: DFA của phần tử card trong ví dụ 3.14 Ví dụ 3.14: Xem xét một DTD được định nghĩa như sau:
<!DOCTYPE addressBook[
<!ELEMENT addressBook (card*)>
<!ELEMENT card ((name | (givenName, familyName)), email, note?)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT givenName (#PCDATA)> <!ELEMENT familyName (#PCDATA)> <!ELEMENT email (#PCDATA)>
<!ELEMENT note (#PCDATA)> ]>
Ví dụ 3.15: Một tài liệu xml tương ứng với DTD trong ví dụ 3.14. <addressBook> <card> <givenName>Hariharan</givenName> <familyName>Iyer</familyName> <email>hari@gmail.com</email> </card> <card> <name>Priti Shankar</name> <email>priti@gmail.com</email> <note>Hariharan’s advisor</note> </card> </addressBook>
Trong hình 3.4, có hai loại trạng thái trong máy tự động: có nhiều transition đầu vào và chỉ có một transition đầu ra duy nhất. Các biểu tượng mà được gán nhãn cho transition đầu ra duy nhất không phải mã hóa vì xác suất của chúng là 1. Do đó quá trình mã hóa số học các biểu tượng chỉ cần được thực hiện tại các trạng thái state có nhiều hơn một transition đầu ra. Phần tử mà có thuộc tính #PCDATA sẽ gọi đến một bộ mã hóa số học. Bộ mã số học này sẽ sử dụng một mô hình chung cho tất cả các thể hiện của thuộc tính đó và mã hóa chúng với cùng một tập hợp các bảng tần số.
Quá trình hoạt động của máy tự động được thực hiện theo trình tự như sau: - Nhập DFA của phần tử.
- Nếu chỉ có một cạnh transition ra khỏi trạng thái state của một phần tử thì không làm gì cả.
- Nếu phần tử có một thuộc tính #PCDATA thì mã hóa chuỗi các biểu tượng ký hiệu bằng cách sử dụng bảng tần số được kết hợp với phần tử đó.
- Nếu phần tử có nhiều hơn một cạnh transition ra khỏi một trạng thái state của phần tử thì sử dụng bộ mã hóa số học cho trạng thái đó và chuyển đến trạng thái bắt đầu của DFA cho phần tử đó.
Chú ý: XAUST sử dụng một bộ chứa container chung cho tất cả dữ liệu mà được kết hợp với mỗi phần tử.
Ví dụ 3.16: Xét phần tử A được mô tả như sau: <!ELEMENT A ((B | C), D)>
Ta thấy, phần tử D sẽ không phải mã hóa, tuy nhiên vẫn phải mã hóa cho phần tử B và C.
3.3.4. Quá trình nén và giải nén sử dụng XAUST
Trạng thái của bộ nén là một cặp element, state trong đó element biểu diễn phần tử hiện tại mà DFA XAUST của nó đi qua và sate là trạng thái của DFA. Giả sử rằng state hiện tại của bộ mã hóa Encoder là i, j . Khi gặp một thẻ mở cho phần tử k trong tài liệu, cặp trạng thái hiện tại của bộ mã hóa Encoder được lưu trữ trong stack và DFA cho phần tử k được nhập vào. Trạng thái mới của bộ mã hóa Encoder bây giờ là k, 0 . Khi gặp phải thẻ đóng của phần tử k, stack bị pop và trạng thái mới của bộ mã hóa Encoder là i, j+1 . Mỗi trạng thái có một mô hình số học mà nó được sử dụng để mã hóa trạng thái tiếp theo.
Ví dụ 3.17: Xét phần tử A được mô tả như sau: <!ELEMENT A ((#PCDATA | B)*)>
Trong ví dụ 3.17, có hai transition cho trạng thái bắt đầu của DFA cho phần tử A. Một transition triệu gọi mô hình số học cho #PCDATA. Một transition khác triệu gọi DFA cho phần tử B sau khi đẩy push trạng thái hiện tại vào trong stack.
Đoạn mã giả cho bộ mã hóa Encoder compressor và bộ giải mã Decoder Decompressor được mô tả như sau:
void Encoder() {
ExitLoop = true;
//StateStruct is a pair of int(ElementIndex, Statelndex) //Elementlndex represents the automaton //Statelndex is the state in the above automaton
StateStruct CurrState(0, 0); while(ExitLoop == false) {
Type = GetNextType(FilePointer, Elementlndex); switch(Type)
case OPENTAG:
//Encode ElementIndex in CurrState context EncodeOpenTag(CurrState, Elementlndex); Stack.push(CurrState);
CurrState = StateStruct(ElementIndex, 0); break;
case CLOSETAG:
//Encode CLOSETAG in CurrState context EncodeCloseTag(CurrState) if(Stack.empty() == true) { ExitLoop = true; } else { CurrState = Stack.pop();
//Make state transition in CurrState.Elementlndex //automaton and get the next state
CurrState.Statelndex =
MakeStateTransition(CurrState,Elementlndex); }
break; case PCDATA:
//Encode Pcdata in Currstate context EncodePcdata(CurrState); CurrState.Statelndex = MakeStateTransition(CurrState, PCDATA); break; } } } void Decoder() { ExitLoop = true; StateStruct CurrState(0, 0); while(ExitLoop == false) {
//Decode the type in CurrState context
Type = DecodeNextType(FilePointer, CurrState, Elementlndex);
switch(Type) {
//Write open tag of the Element of Elementlndex WriteOpenTag(Elementlndex); Stack.push(CurrState); CurrState = StateStruct(ElementIndex, 0); break; case CLOSETAG:
//Write close tag of the Element of ElementIndex WriteCloseTag(Elementlndex); if(Stack.empty() == true) { ExitLoop = true; } else { CurrState = Stack.pop(); CurrState.Statelndex = MakeStateTransition(CurrState,Elementlndex); } break; case PCDATA: DecodePcdata(CurrState); CurrState.Statelndex = MakeStateTransition(CurrState, PCDATA); break; } } } 3.4. XSAQCT 3.4.1. Tổng quan về XSAQCT
XSAQCT được phát âm là exact là một bộ nén XML phi cú pháp free-grammar) có khả năng truy vấn. XSAQCT mượn kỹ thuật của các bộ nén khác để bóc tách cấu trúc tài liệu từ các giá trị dữ liệu. Điểm mới của XSAQCT là bộ nén này mã hóa thông tin tài liệu ngắn gọn và súc tích hơn so với các thông tin đầu vào. Sau đó nó sử dụng các bộ nén dữ liệu nền back-end phù hợp để nén bộ chứa lưu trữ cấu trúc tài liệu và bộ chứa lưu trữ giá trị dữ liệu. Phương pháp tiếp cận của XSAQCT là sử dụng các bộ chứa đủ lớn để có thể đạt được tỉ lệ nén hiệu quả, đồng thời cấu trúc của bộ chứa cũng không yêu cầu phải đ i hỏi giải nén toàn bộ tài liệu XML nén khi thực hiện một truy vấn. XSAQCT cũng được thiết kế để hỗ trợ giải nén lazy decompression tức là giải nén tài liệu ít nhất có thể khi thực hiện truy vấn.
XSAQCT được mô tả như là một ứng dụng cơ sở dữ liệu mà tập trung vào quá trình nén có khả năng truy vấn với sự truy cập ngẫu nhiên và tốc độ thực thi của quá trình giải nén. Bên cạnh đó, XSAQCT c n là một bộ nén tương tác interactive compressor mà có thể thực hiện bất kỳ loại truy vấn nào. Nó hỗ trợ cả quá trình nén không mất mát lossless
compression) lẫn hỗ trợ cho phép loại bỏ các khoảng trắng thừa. XSAQCT cũng áp dụng đánh chỉ mục và sử dụng bộ nhớ đệm để cải thiện tốc độ xử lý.
3.4.2. Kiến trúc của XSAQCT
Kiến trúc của XSAQCT được minh họa bởi hình 3.5 trong đó các hình chữ nhật được đánh bóng mờ biểu diễn các giai đoạn trung gian của quá trình nén.
Cho một tài liệu D, XSAQCT sử dụng SAX duy nhất quét, phân tích và mã hóa tài liệu D để tạo ra một cây chú thích annotated tree TA,D . Cũng tại thời điểm đó, các giá trị dữ liệu được đưa vào những bộ chứa thích hợp. Bước tiếp theo, TA,D được nén bao gồm hai bước. Bước thứ nhất ghi các chú thích của nó vào trong một bộ chứa. Bước thứ hai cây khung (skeleton tree) (TD không c n có chú thích được đưa vào một bộ chứa khác.
Cuối cùng, tất cả các bộ chứa c n lại được nén bằng cách sử dụng các bộ nén nền (back-end được xác định bởi người sử dụng và được ghi lại tạo đầu ra CD.
Chú ý rằng TA,D biểu diễn chính xác cấu trúc nhưng cô đọng súc tích hơn cấu trúc của tài liệu đầu vào D. TA,D giữ lại tất cả thông tin về thứ tự của các phần tử, thuộc tính.
XSAQCT sử dụng một container duy nhất cho quá trình lưu trữ các giá trị text của tất cả đường dẫn tương đương nhau ví dụ, các đường dẫn /a/b/t1, a/b/t2 và a/c/t1 với t1, t2 là các chuỗi text thì ta sẽ có /a/b/t1 tương đương /a/b/t2, trong khi đó a/b/t1 không tương đương với a/c/t1 .
Mỗi bộ chứa có thể được nén bằng cách sử dụng các bộ nén nền back-end) khác nhau phụ thuộc vào loại giá trị trong bộ chứa container. Các bộ nén nền back-end được sử dụng trong XSAQCT bao gồm: gzip, bzip2…, người dùng có thể bổ sung thêm nhiều bộ nén khác.
Quá trình giải nén bao gồm các bước sau:
1. Sử dụng bộ giải nén nền back-end decompressor để khôi phục lại nội dung của tất cả bộ chứa.
2. Chú thích lại re-annotation : sử dụng các chú thích và cây khung TD để tạo lại TA,D. 3. Khôi phục lại restoring : sử dụng TA,D để khôi phục lại tập tin được nén.
Ví dụ 3.18: Xem xét tài liệu D được minh họa trong hình 3.6. Ta thấy rằng, cây tài liệu không có bất kỳ các giá trị dữ liệu nào. Có 3 đường dẫn tương đương /b/c và hai đường dẫn tương đương a/b/e. Cây chú thích TA,D biểu diễn tài liệu D được minh họa trong hình 3.7. Các đường dẫn tương đương nhau đã được merge lại nên trong ví dụ này chỉ có một đường dẫn a/b/c và một đường dẫn a/b/e. Để hỗ trợ quá trình giải nén, chú thích được thêm vào các node của cây TA,D. Chú thích được kết hợp với node n sẽ là tổng số lượng con của m được gán nhãn bởi n, trong đó m là cha của node n. Trong ví dụ 3.18, node b trong cây TA,D được chú thích [3] bởi vì có 3 con được gán nhãn bởi “b” là con của node “a‟ trong cây tài liệu D. Node “e” được gán nhãn [0,0,2] bởi vì trong tài liệu D, không có con nào được gán nhãn “e‟ cho hai lần xuất hiện đầu tiên của node “b”, và có 2 con được gán nhãn “e” cho lần xuất hiện thứ 3 của node “b”.
Hình 3.6: Minh họa một tài liệu D đơn giản [20]
3.4.3. Quá trình xử lý thuộc tính và nội dung tài liệu được trộn
Thuộc tính được xử lý giống như phần tử và các chú thích của chúng được ghi vào cây chú thích TA,D. Hình 3.8 minh họa một tài liệu đơn giản với nội dung được trộn lẫn giữa các phần tử, thuộc tính và node văn bản. Cây chú thích TA,D và các bộ chứa văn bản được minh họa trong hình 3.9. Các node được đánh dấu “*” nếu phần tử tương ứng có nội dung được trộn và trong trường hợp này một văn bản rỗng được minh họa bởi hình hộp chứa “0” được thêm vào các bộ chứa văn bản khi cần thiết.
Trong bộ nén XASQCT, các giá trị dữ liệu của những đường dẫn tương đương nhau thì được lưu trữ vào một bộ chứa container riêng. Xét ví dụ trong hình 3.9 ta có t1 và t2 cùng đường dẫn /a được lưu trữ trong một bộ chứa; t3 được lưu trữ riêng trong một bộ chứa; t4, t5, t6 và t7 cùng đường dẫn /a/b được lưu trữ trong cùng một bộ chứa; t11 và t12 cùng đường dẫn /a/b/e được lưu trữ trong cùng một bộ chứa; t8, t9, t13 cùng đường dẫn /a/b/c được lưu trữ trong cùng một bộ chứa; t10 được lưu trữ trong một bộ chứa riêng; chú thích được gán cho “a” là [1]; chú thích được gán cho “b” là [3]; chú thích được gán cho “e” là [0,0,2]; chú thích được gán cho “c” là [1,1,1]; chú thích được gán cho “d” là [0,1,0].
Hình 3.8: Quá trình xử lý nội dung tài liệu được trộn [20]
3.4.4. Quá trình cài đặt XSAQCT
3.4.4.1. Quá trình xây dựng cây chú thích TA,D 3.4.4.1.1. Đặc điểm của cây chú thích TA,D 3.4.4.1.1. Đặc điểm của cây chú thích TA,D
Cây chú thích TA,D của tài liệu có độ cao bằng độ cao của tài liệu D, nhưng độ rộng lại hẹp hơn độ rộng của D. Chú thích của node A trong cây TA,D được ký hiệu là ann(A)=[a1,…,ak] và |ann A | là số lượng những số nguyên trong ann A , {A} là tổng của a1,…,ak. Xem xét các thuộc tính sau đây:
1. Trong D có a1,…,ak sự xuất hiện của A. 2. Nếu A có con B1,…,Bm trong TA,D thì:
2.1. ann(Bj) = [bj,1,…,bj,{A}]
Số lượng những số nguyên trong chú thích của từng node con bằng tổng số của những số nguyên trong node cha.
2.2.Trong D, node Aj có:
bj,1 các con được gán nhãn bởi B1. …
bj,{A} các con được gán nhãn bởi B{A}.
Trong ví dụ 3.18, node “b” trong TA,D có ann b =[3] và theo 1 có 3 sự xuất hiện của node “b” trong D, theo thuộc tính 2.1 trong phần 3.4.4.1.1, chú thích của các node con “e”, “c”, “d” của node “b” có 3 số nguyên: node “e” là 0,0,2; node “c” là 1,1,1; node “d” là 0,1,0. Để xem ví dụ của trường hợp thuộc tính 2.2 trong phần 3.4.4.1.1, xem chi tiết trong hình 3.15. Node “$” là con của node “a” có hai con là node “s” và “z”. Node “s‟ được chú thích là [1,2,0,1,0] và node “z” được chú thích là [0,1,1,0,0], nhưng trong hình 3.16, ta thấy có năm sự xuất hiện của “$” trong D.
- Lần xuất hiện đầu tiên của “$” có một con được gán nhãn bởi “s” và không có con nào được gán nhãn bởi “z”.
- Lần xuất hiện thứ hai của “$” có hai con được gán nhãn bởi “s” và một con được