2013-05-31 1 views
3

, пожалуйста, помогите, я делаю анализ html с использованием MSHTML. Мой код для получения всех атрибутов конкретного тега как этогоВ анализе HTML Получить атрибуты тега в Cpp, используя IHTMLDOMAttribute

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 возвращает false для атрибута value.

Мой выход

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/en-us/library/cc288325.aspx). Например, указанный всегда имеет значение ИСТИНА, когда IE находится в IE9 «Режим стандартов». –

ответ

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 дня и ответа нет, я выбрал еще один парсер HTML, упомянутый в другом потоке SO – 999k

2

Я никогда не работал с этим раньше, но, по словам библиотеки документации и DOM спецификации, кажется, что get_nodeValue() делает разные вещи в зависимости от типа объекта «узла». Попробуйте позвонить get_nodeValue() или get_nodeName() на объект IHTMLDOMNode. Кажется очевидным, что некоторые свойства, такие как «значение», «идентификатор» и «имя», не являются частью коллекции атрибутов в DOM.


Mshtml документы:

DOM спецификации:

+1

Спасибо за ваше время. Фактически get_nodeName() возвращает имя тега, т.е. INPUT в моем случае не имя атрибута. И я проверил почти все те интерфейсы IHTMLDOMNode также в моем коде. – 999k

+0

Также проблема не в интерфейсе funtion get_nodeValue(). Из моей заметки ясно, что эта функция возвращает правильное значение, но get_specified возвращает false, даже если она указана в теге – 999k

+0

Извините, я, должно быть, неправильно понял вопрос (никогда не использовал эту библиотеку раньше). В обоих документах, перечисленных в моем ответе, указано, что указанный флаг должен быть истинным для атрибута value. Это старая библиотека MS, и, возможно, у нее могут быть ошибки. Я бы рекомендовал переключиться на более общий механизм анализа XML, например, cpz, предложенный в его ответе. – idoby

3

Вы действительно заботитесь о знаке указанного? Вы сказали, что хотите обработать все атрибуты, я думаю, что если это так, вам не нужно заботиться о указанном флаге, просто обработайте все атрибуты.

Другое дело, если бы я был вами, я буду использовать CComPtr вместо всего голого указателя com.

+0

Я не так хорошо знаком с Visual Studio и другими передовыми терминами на C++, такими как CComPtr. Я не знаю, какие атрибуты есть в моем теге. Поэтому, если я использую get_nodeValue(), не проверяя указанный флаг, его возвращающий нулевой указатель и даже плохой указатель несколько раз. – 999k

2

проверьте тип ввода, затем введите запрос для интерфейса IID_IHTMLInputElement, затем используйте get_value.

Смежные вопросы