2013-05-31 46 views
3

請幫助我使用MSHTML進行html解析。我對得到一個特定標籤的所有屬性代碼是這樣的在HTML解析中使用IHTMLDOMAttribute獲取Cpp中標記的屬性

void GetAttributes(MSHTML::IHTMLElementPtr pColumnInnerElement) 
{ 
    IHTMLDOMNode *pElemDN = NULL; 
    LONG lACLength; 
    MSHTML::IHTMLAttributeCollection *pAttrColl; 
    IDispatch* pACDisp; 
    VARIANT vACIndex; 
    IDispatch* pItemDisp; 
    IHTMLDOMAttribute* pItem; 
    BSTR bstrName; 
    VARIANT vValue; 
    VARIANT_BOOL vbSpecified; 
    pColumnInnerElement->QueryInterface(IID_IHTMLDOMNode, (void**)&pElemDN); 
    if (pElemDN != NULL) 
    { 
     pElemDN->get_attributes(&pACDisp); 
     pACDisp->QueryInterface(IID_IHTMLAttributeCollection, (void**)&pAttrColl); 
     pAttrColl->get_length(&lACLength); 
     vACIndex.vt = VT_I4; 
     for (int i = 0; i < lACLength; i++) 
     { 

      vACIndex.lVal = i; 
      pItemDisp = pAttrColl->item(&vACIndex); 
      if (pItemDisp != NULL) 
      { 
       pItemDisp->QueryInterface(IID_IHTMLDOMAttribute, (void**)&pItem); 
       pItem->get_specified(&vbSpecified); 
       pItem->get_nodeName(&bstrName); 
       pItem->get_nodeValue(&vValue); 

       if (vbSpecified) 
       cout<<_com_util::ConvertBSTRToString(bstrName)<<" :"<<_com_util::ConvertBSTRToString(vValue.bstrVal)<<endl; 
       pItem->Release(); 
      } 
      pItemDisp->Release(); 

     } 
     pElemDN->Release(); 
     pACDisp->Release(); 
     pAttrColl->Release(); 
    } 
} 

的問題是對於給定的標籤<input id="Switch l_id2" class="pointer" name="Switch" onclick='SetControl("Switch l",1)' type="button" value="OK">它打印除了value屬性的所有屬性。 get_specified函數返回falsevalue屬性。

我的輸出

id :Switch l_id2 
class :pointer 
onclick :SetControl("Switch l",1) 
type :button 
name :Switch 

任何想法,爲什麼?還有哪些其他屬性可能會有這個問題?

注意

我試過這樣。它顯示value的正確屬性結果。

 if (strcmp(_com_util::ConvertBSTRToString(bstrName), "value") == 0) 
     { 
      cout<<_com_util::ConvertBSTRToString(bstrName)<<" :"<<_com_util::ConvertBSTRToString(vValue.bstrVal)<<endl; 
     } 
+0

你的筆記是什麼意思?是否由於vbSpecified測試? –

+0

我補充說明顯示正確的值在vValue.bstrVal。但仍然vbSpecified返回false – 999k

+0

不確定指定的標誌總是有意義的。您是否嘗試更改文檔兼容模式(http://msdn.microsoft.com/zh-cn/library/cc288325.aspx)。例如,當IE處於IE9'標準模式'時,指定爲始終爲TRUE。 –

回答

3

如果您使用託管(CLI)VC++,那麼您可以考慮HTML Agility Pack,可通過nuget獲得。

如果不需要堅持MSHTML,那麼可能你可以選擇將HTML文檔解析爲XML文檔。這樣你就可以用很多的靈活性來解析所有的標籤和屬性。有很多C++的XML解析器可用。

這個庫看起來小巧簡單而有效的(可用於多種平臺):https://github.com/leethomason/tinyxml2

另一條是:http://pugixml.org/

此鏈接可以幫助你,如果你想擺脫MSHTML依賴:http://www.codeproject.com/Articles/30342/Remove-Microsoft-mshtml-dependency

+1

感謝您的時間和答覆。是的,我知道有很多其他解析器。等待2 3天后,在這裏沒有回覆,我選擇了另一個SO線程中提到的另一個HTML解析器 – 999k

2

我從來沒有與此工作過,但據庫文檔和DOM規範,似乎get_nodeValue()做不同的事情取決於「節點對象」的類型。嘗試在IHTMLDOMNode對象上調用get_nodeValue()get_nodeName()。似乎很清楚,諸如「值」,「ID」和「名稱」之類的一些屬性不屬於DOM下屬性集合的一部分。


MSHTML文檔:

DOM規範:

+1

謝謝你的時間。實際上get_nodeName()返回標籤名稱,即INPUT,在我的情況下不是屬性名稱。我也在我的代碼中檢查了幾乎所有IHTMLDOMNode的接口。 – 999k

+0

另外問題不在接口函數get_nodeValue()中。從我的筆記中可以明顯看出,這個函數返回正確的值,但get_specified返回false,即使它在標籤中指定。 – 999k

+0

對不起,我一定誤解了這個問題(以前從未使用過這個庫)。我的答案中列出的兩個文檔都聲明指定的標誌對於value屬性應該爲true。這是一箇舊的MS庫,它可能有錯誤。我建議切換到更通用的XML解析引擎,如cpz在他的答案中建議的。 – idoby

3

你真的關心指定的國旗嗎?你說你想處理所有的屬性,我想如果這種情況你不需要關心指定的標誌,只需處理所有的屬性。

其他的事情是,如果我是你,我會用CComPtr來代替所有的裸指針。

+0

我對Visual Studio和CComPtr等其他高級C++術語並不熟悉。我不知道我的標籤中有哪些屬性。所以如果我使用get_nodeValue()來檢查指定的標誌,它會返回空指針,甚至有時會出現壞指針。 – 999k

2

檢查輸入類型,然後查詢IID_IHTMLInputElement接口,然後使用get_value