Chương 3 Phân Tích Đề Tài
4.3 Hiện Thực Cơ Chế Duyệt Trang HTML
Trong phần phân tích chúng ta đã phần nào hiểu được cơ chế duyệt trang HTML cũng như kiến trúc của một trang web bình thường nhất.
SVTH: Trần Thanh Tùng Trang 74/84 Bây giờ chúng ta sẽ đi vào chi tết quá trình duyệt trang HTML. Trang HTML được xây dựng theo kiến trúc DOM nên thứ tự cũng như thành phần là không thay đổi.
Từ hình trên ta biết rằng các phần tử trong trang đều có thứ bật mỗi phần tử là một đối tượng, từ đó ta có thể thao tác trên mỗi đối tượng riêng lẽ khi duyệt qua từng phần tử.
Ta đã xát định được cấu trúc cũng như đặc tính của trang HTML, nhưng nói thì rất khó hiểu, bây giờ ta tìm hiểu một đoạn mã cụ thể và tiến hành duyệt theo từng bước một :
Xét đoạn mã sau :
<p > <h1>khúc thơ hay </h1>
<h2> bất tri tam bách dư niên hậu <br>
Thiên hạ hà nhân khóc tố như</h2>
<h2> đầu giường ánh trăng rọi <br>
Sàn tiền minh nguyệt quang</h2>
Không ra bài nào cả </p>
Phân tích đoạn mã này :
Từ Node P ta có 4 node con.
SVTH: Trần Thanh Tùng Trang 75/84 Ba node đầu có nodetype = 1, node cuối có nodetype = 3. Đây là dấu hiệu nhận diện đối tượng text trong trang HTML.
Vậy từ node P nếu lấy firstChild ta được node h1, lấy nextSibling ta được node = null. Lấy lastChild được node text “không ra bài nào cả”.
Sau đây là mã chương trình duyệt trang HTML để lấy nội dung text : mshtml.IHTMLDOMNode iDomNode = e;
while (iDomNode != null) {
XuLyText(iDomNode);
if (iDomNode.hasChildNodes()) DuyetNode(iDomNode.firstChild);
iDomNode = iDomNode.nextSibling;
}
Trong đoạn mã này ta dùng giải thuật đệ quy để duyệt các phần tử của trang HTML. Ban đầu ta cung cấp cho nó node đầu tiên của trang, thường là node chú thích, tức node có nodename là #COMment, nodetype = 8. và từ node đó cứ duyệt hết node con của nó rồi lại tới nói nextSibling của nó. Đối với mỗi node con lại duyệt như vậy và cứ như thế cho đến hết.
Trong đoạn mã trên có hàm XuLyText hàm này cho ta lọc ra những node text tức node có nodetype =3. node text không có node con. Sau khi lọc song ta tiến hành chuyển mã ký tự đối với text vừa nhận được.
Nội dung trang HTML đã được sử lý, thế nhưng ta chỉ chuyển mã nội dung văn bản thôi thì chưa đủ, nếu không có font hoăc font không đúng thì trang web vẩn hiển thị sai. Vậy chúng ta sẽ hiện thực cơ chế tìm, tách và chuyển font cho phù hợp. Chú ý rằng, không phải font nào cũng có font tương ứng với nó ở bản mã khác, tức không phải font nào cũng chuyển được. Vì vậy, giải pháp cho vấn để này là: đối với những font không chuyển được ta tạm thời thay băng font “Times New Roman”, đây chỉ là giải pháp tạm thời.
Và đây sẽ là giải thuật duyệt trang HTML để lấy và chuyển font:
Trong chương 3 chứng ta đã tìm hiểu về thuộc tính tag cũng như đặc tính của thuộc tính font, những nơi font xuất hiện và đối tượng sử lý font.
SVTH: Trần Thanh Tùng Trang 76/84 Thuộc tính font trong các thẻ tag chỉ có trong thẻ FONT với thuộc tính là face.
Còn lại là 3 dạng của CSS. Một trang web bất kì thường sử dụng CSS để thiết lập thuộc tính font cũng như các thuộc tính về kích thước, màu sắc…riêng chúng ta chỉ quan tâm đến thuộc tính font.
Chúng ta sẽ xem lại ba dạng CSS có chứa thuộc tính font :
- External Style Sheet : dạng này chứa một file css bên ngoài và được tham chiếu đến bằng đối tượng IHTMLLinkElement.
IHTMLLinkElement : đây là interface cung cấp những phương thức để truy cập phần tử link , phần tử này được được sát định bằng một đường link đến một tài liệu external.
Interface này cung cấp thuộc tính StyleSheet để trả về một đối tượng IHTMLStyleSheet.
SVTH: Trần Thanh Tùng Trang 77/84 - Dạng kế tiếp là : DocumentWideStyle. Dạng CSS này thường nằm được thể hiện là tag Style trong phần Head. Ta chỉ cần duyệt tag này và lấy thuộc tính của nó là được. đối tượng Style cung cấp cho ta interface IHTMLStyleSheet.
Interface này cho phép truy cập một đối tượng được mô tả như một single style sheet trong tài liệu.
SVTH: Trần Thanh Tùng Trang 78/84 Trong các thuộc tính, ta chỉ quan tâm đến thuộc tính Rules của interface này, trị trả về của thuộc tính này là một interface IHTMLStyleSheetRulesCóllection.
Interface IHTMLStyleSheetRulesCollection cung cấp thuộc tính items để lấy thuộc tính style rồi font-family từ đó ta có thể xét thuộc tính font cho từng phần tử trong tập hợp này.
Để giảm độ phức tạp trong giải thuật duyệt, duyệt font được tách rời làm hai lần duyệt:
- lần đầu duyệt trong tag Head để lấy CSS từ External Style và DocumentWideStyle.
public void SetFontOutTerCSS(mshtml.IHTMLDOMNode e) {
try {
mshtml.IHTMLStyleSheet ihsShet = ((mshtml.IHTMLLinkElement)e).styleSheet;
string stemp = ihsShet.cssText;
int dem = ihsShet.rules.length;
mshtml.HTMLStyleSheetRulesCóllection issrCóllec = ihsShet.rules;
for (int i = 0; i < dem; i++) {
string schuabiet = issrCollec.item(i).selectorText;
string stam = issrCollec.item(i).style.font;
string sbien = issrCollec.item(i).style.fontFamily;
issrCollec.item(i).style.fontFamily = ConverFonts(sbien);
}
SVTH: Trần Thanh Tùng Trang 79/84 }
catch (Exception exc) {
MessageBox.Show(exc.ToString());
} }
- lần hai: duyệt từ body, lấy thuộc tính font từ tag font và font CSS dạng InerStyle.
public void DuyetNodeHead(mshtml.HTMLDocument e) {
mshtml.IHTMLDOMNode ihdNodeHead = null ; if (e.firstChild.nodeType.Equals(8))
ihdNodeHead = e.firstChild.nextSibling.firstChild;
else
ihdNodeHead = e.firstChild.firstChild;
// phan tren lay tu node Head
mshtml.IHTMLDOMNode ihNodeDuyet = ihdNodeHead.firstChild;
while (ihNodeDuyet != null) {
if(ihNodeDuyet.nodeName.Equals("STYLE")) SetFontTagStyle(ihNodeDuyet);
if (ihNodeDuyet.nodeName.Equals("LINK")) SetFontOutTerCSS(ihNodeDuyet);
ihNodeDuyet = ihNodeDuyet.nextSibling;
} }
Như vậy ta đã duyệt toàn bộ trang web và lấy được text rồi font từ inner đến external style sheet.
4.4 Hiện Thực Cơ Chế Chuyển Mã
Nguyên lý của việc chuyển mã từ bản mã này sang bản mã khác đã được giới thiệu trong chương 3. ở đây chúng ta sẽ hiện thực các phương thức hổ trợ việc chuyển mã.
SVTH: Trần Thanh Tùng Trang 80/84 Thầy Nguyễn Văn Hiệp đã cung cấp đối tượng COM BkTrans đảm trách nhiệm vụ chuyển mã văn bản, chuyển mã font chữ…
Các phương thức của đối tượng BkTrans :
Khai báo đối tượng BkTrans:
BKTRANSLib.IBkTransLib m_bktrans;
public Form1() {
InitializeCOMponent();
m_bktrans = new BKTRANSLib.BKTRANSLibClass();
int i = m_bktrans.Init();
}
4.5 Chương Trình Đề Mô
Chương trình của chúng ta xuất ra file .dll và được đăng ký bằng trình RegAsm.
SVTH: Trần Thanh Tùng Trang 81/84 Internet explorer không có font, hiển thị sai nội dung :
Kích hoặt đối tượng COM để lắng nghe sự kiện và thực hiển chuyển mã :
SVTH: Trần Thanh Tùng Trang 82/84 Sau khi đăng ký COM và hiển thị lại :