IE 解析 Web Page DOM結(jié)構(gòu) (二)新一篇: C++ STL輕松導(dǎo)學(xué)接下來的兩篇我將介紹怎樣從DOM流中解析出組成網(wǎng)頁的最基本的兩種元素:文字和圖像。
上一篇我說過網(wǎng)頁是由許多嵌套的frame組成,而每一個frame都是一個獨(dú)立的單元,他們包含自己的文字和圖片。解析文字和圖片有以下兩種情況:
1. 他們都直接放置在網(wǎng)頁“BODY”層,此時我不用考慮這些frame導(dǎo)致的布局影響。這是最簡單的一種情形。
2. 而常見的情形是他們被放置于嵌套的frame中,比如Button控件上的文字,TextBox控件中的文字等。
l 文字
1. “BODY“層的文字
文字在DOM語言中有好多種標(biāo)簽可以代表他,比如Label,Title,和Anchor等等。他們都表示有文字。
· 首先,我需要得到文字的位置以及他的本體文字,這可一從IHTMLElement接口中獲得。
IHTMLElement Members(從MSDN摘錄的片段)
offsetParent
Retrieves a reference to the container object that defines the IHTMLElement::offsetTop and IHTMLElement::offsetLeft properties of the object.
offsetHeight
Retrieves the height of the object relative to the layout or coordinate parent, as specified by the IHTMLElement::offsetParent property.
offsetLeft
Retrieves the calculated left position of the object relative to the layout or coordinate parent, as specified by the IHTMLElement::offsetParent property.
offsetParent
Retrieves a reference to the container object that defines the IHTMLElement::offsetTop and IHTMLElement::offsetLeft properties of the object.
offsetTop
Retrieves the calculated top position of the object relative to the layout or coordinate parent, as specified by the IHTMLElement::offsetParent property.
offsetWidth
Retrieves the width of the object relative to the layout or coordinate parent, as specified by the IHTMLElement::offsetParent property.
innerText
Sets or retrieves the text between the start and end tags of the object.
下面是可行的偽代碼:
long ltop, lleft, lHeight, lwidth;
hr = spElement->get_offsetLeft(&lleft);
hr = spElement->get_offsetTop(<op);
hr = spElement->get_offsetHeight(&lHeight);
hr = spElement->get_offsetWidth(&lwidth);
BSTR bstrInnerText;
hr = spElement->get_innerText(&bstrInnerText);
· 關(guān)于文字的字體風(fēng)格,如字體大小,字體族,是否加粗,傾斜等等,我就只能從CSS流中解析。而CSS流的代表接口就是IHTMLCurrentStyle。
IHTMLCurrentStyle Members(從MSDN摘錄的片段)
fontFamily
Sets or retrieves the name of the font used for text in the object.
fontSize
Sets or retrieves a value that indicates the font size used for text in the object.
fontStyle
Sets or retrieves the font style of the object as italic, normal, or oblique.
fontVariant
Sets or retrieves whether the text of the object is in small capital letters.
fontWeight
Sets or retrieves the weight of the font of the object.
下面是可行偽代碼:
CComQIPtr<IHTMLElement> spElement;
CComQIPtr<IHTMLElement2> spElement2(spElement);
CComQIPtr<IHTMLCurrentStyle>spCurrentStyle;
spElement2->get_currentStyle(&spCurrentStyle);
VARIANT varfontSize;
varfontSize.vt = VT_BSTR;
spCurrentStyle->get_fontSize(&varfontSize);
VARIANT varfontWeight;
varfontWeight.vt = VT_BSTR;
spCurrentStyle->get_fontWeight(&varfontWeight);
VARIANT varHeight;
varHeight.vt = VT_BSTR
spCurrentStyle->get_height(&varHeight);
這里你所取得的fontFamily的值是一個字體族列表,其中的每個字體族用分號隔開以防止當(dāng)有多種字體族混雜在一起。此值主要由兩部分組成:字體族名稱和通用字體族名稱。如果字體族名稱包含空白符,它應(yīng)該出現(xiàn)一個或兩個引號;通用字體族名稱不用包含在引號中。
為什么要這樣組織字體族名稱呢?這主要是因?yàn)槟悴恢揽蛻舳税惭b了什么字體, 你應(yīng)該提供用戶一個備用的字體族 – 通用字體族名稱在字體族名稱列表的末尾,防止如果客戶端沒有安裝字體族名稱指定的字體時,可以用通用字體族名稱來替代。
這個字體族名稱列表也可以包含嵌入字體。此外,關(guān)于fontFamily的默認(rèn)值可以通過Microsoft Internet Explorer->Internet Options menu->General tab->Fonts button來設(shè)置。
綜上所述,IE瀏覽器是這樣來應(yīng)用字體的:首先他會從DOM中解析出fontFamily的字體列表,然后他會嘗試其中的每一個字體,直到找到一種客戶端已經(jīng)安裝的字體族。如果到列表末尾,IE瀏覽器依然沒有找到相應(yīng)的字體,那么他就會使用IE設(shè)置的那個默認(rèn)字體。
此外,在上面的偽代碼中所得到的字體大小,高度,寬度等數(shù)據(jù),他們返回的值有可能不是絕對的數(shù)值,如8pt。相反,它可能是一種相對值(相對上一層字體),比如:xx-small,x-small,larger,smaller等等。這不可避免地要求我們自己將這些抽象概念轉(zhuǎn)化為絕對數(shù)值。特別是,如果給出的是百分比,我們可能需要遞歸算出這些數(shù)值。
最糟糕的是,有時候你可能取得的是負(fù)值,比如:“-1”,“-2”。這意味著字體大小必須轉(zhuǎn)化為設(shè)備單位,而且匹配它的絕對數(shù)值通過可用字體字符的高度。
· 文字顏色是個很麻煩的問題,可以用下面的代碼:
CComQIPtr<IHTMLCurrentStyle>spCurrentStyle;
VARIANT varColor;
varColor.vt = VT_BSTR|VT_I4;
spCurrentStyle->get_color(&varColor);
但是請注意返回的varColor是一個BSTR值,而且是專屬于網(wǎng)頁設(shè)計(jì)的一組顏色值,如果你想使用RGB顏色值,必須自己進(jìn)行轉(zhuǎn)換。而且,DOM常常會簡寫這個顏色值,比如#00ccff,從上面的代碼取出來的值可能是#0cf。
· 文字編碼問題
我們可以在IE瀏覽器中設(shè)置網(wǎng)頁的編碼,這些信息我們也可以從DOM中獲取.
BSTR bstrCharset;
spHTMLDocument2->get_charset(&bstrCharset);
2. 嵌套容器中的文字
我打算以Table控件中的文字為例,其他控件容器中的文字可以按類似的方法來處理
· Get text in Table
許多網(wǎng)頁中都有Table控件,每個Table都有自己的文字。比如,下面這個Table:
Hanna Strategies, Ltd. is among the first software outsourcing service providers in China ‘s IT industry, specializing in the research and development of computer aided design (CAD) and data management software......
這個Table的DOM樹如下所示:(通過IE Dev Toolbar取得)
· 文字分行
網(wǎng)頁中的文字是沒有分行符讓你判斷文字該到哪個字分行,這是一個大麻煩,尤其對于那些做文件格式轉(zhuǎn)化的程序員而言。因?yàn)檫@意味著雖然你可以得到上面的那一大段文字,但是,你不知道怎么來斷行。唯一可行的辦法就是自己設(shè)計(jì)算法來分行,但只是一件非常復(fù)雜的事。
你想一想,你既要考慮字體目前的大小,還要調(diào)整Table一行是多寬,從而計(jì)算每一行最多可以放幾個字。其中,還要加上字跟字,行跟行之間的間距值。這實(shí)在是個很煩瑣的事。
· Table中文字的位置
現(xiàn)在文字的位置需要考慮連個因素:一個是文字相對于Table的位置;另一個是整個Table相對于網(wǎng)頁的位置。
IHTMLTable Members(從MSDN摘錄)
align
Sets or retrieves a value that indicates the table alignment.
cellPadding
Sets or retrieves the amount of space between the border of the cell and the content of the cell.
cellSpacing
Sets or retrieves the amount of space between cells in a table.
height
Sets or retrieves the height of the object.
width
Sets or retrieves the width of the object.
IHTMLTableCell Members(從MSDN摘錄)
colSpan
Sets or retrieves the number columns in the table that the object should span.
height
Sets or retrieves the height of the object.
noWrap
Sets or retrieves whether the browser automatically performs wordwrap.
rowSpan
Sets or retrieves how many rows in a table the cell should span.
vAlign
Sets or retrieves how text and other content are vertically aligned within the object that contains them.
width
Sets or retrieves the width of the object.
關(guān)于這一點(diǎn)我會在后面詳細(xì)討論,這也是一個浩大的解析過程。