Как я могу получить доступ к атрибутам элемента из IXMLDOMNode?

Я строю документ XML DOM на C++. Моя проблема заключается в следующем: я выполняю запрос XPATH от элемента в моем документе, который, как я знаю, вернет другой элемент. Вызов elementPtr->selectSingleNode возвращает IXMLDOMNode. Как я могу получить доступ к атрибутам этого узла?

Часть меня хочет низвести Узел до Элемента, но я не мог заставить актеров работать.

Я старался

MSXML2::IXMLDOMElementPtr pParentElement;
pParentNode->QueryInterface(__uuidof(MSXML2::IXMLDOMElement), 
                            (void**) &pParentElement);

Что приводит к следующей ошибке во время выполнения:

0x0057cc58 _com_error::`scalar deleting destructor'(unsigned int)

Другой путь, который я пробовал, состоял в том, чтобы просто использовать узлы

MSXML2::IXMLDOMNodePtr pParentNode = 
    pParameterElement->selectSingleNode("parent");
MSXML2::IXMLDOMNamedNodeMap* pParentAttributes;
pParentNode->get_attributes(&pParentAttributes);

MSXML2::IXMLDOMNodePtr pCategoryNameNode = 
    pParentAttributes->getNamedItem("Category");
VARIANT value;
pCategoryNameNode->get_nodeValue(&value);
CString categoryName = value;

Это терпит неудачу в "parentNode->get_attributes()".

Кажется, я что-то упустил; API не должен быть таким сложным в использовании.

--редактировать--

Чего мне не хватало, так это того, что вызов selectSingleNode не удался, оставив меня с указателем NULL. Вы не можете вызвать QueryInterface для этого, также вы не можете вызвать get_attributes для него:P

Я выбрал ответ, который соответствует заданному вопросу, а не ответ, который помог мне понять, что я задал неправильный вопрос.

3 ответа

Решение

Я не вижу ничего плохого в том, что вы написали.

Смарт-ком указатели помогут вам конвертировать, если они могут, вам не нужно писать интерфейс запроса самостоятельно.

MSXML2::IXMLDOMNodePtr pParentNode = pParameterElement->selectSingleNode("parent");
MSXML2::IXMLDOMElementPtr pParentElement( pParentNode );

На мой взгляд, использование типов Ptr немного затруднительно, хотя интерфейс MSXML поддерживает их. Вот пример эквивланта с использованием ATL

CComPtr<IXMLDOMNode> node = ...;
CComQIPtr<IXMLDOMElement> elementNode( node );

if( elementNode ) { 
// it was an element!
} else { 
// it's something else try again? 
}

Другая попытка будет выглядеть как...

CComPtr<IXMLDOMNamedNodeMap> attributes;
node->get_attributes( &attributes );
if( attributes ) {
  _bstr_t name( L"category" );
  attributes->getNamedItem(name);
}

И это COM, это всегда трудно использовать в C++:(

Как вы пытались сделать переход от IXMLDOMNode к IXMLDOMElement? Вы не можете просто использовать приведение C++ для этого, так как это COM-объект: вы должны использовать QueryInterface().


Глядя на ваш код QueryInterface (), некоторые мысли:

  • PParentNode определенно не нуль? Я не думаю, что это проблема, учитывая, что вы получаете, но это стоит проверить.
  • Я думаю, что вызов QueryInterface () не совсем верен: вы должны вызывать AddRef() тем или иным образом в возвращаемом интерфейсе, а ваш код - нет. Как отметил другой автор, вы можете получить _com_ptr_t<>, чтобы сделать это для вас:

    MSXML2::IXMLDOMElementPtr pParentElement(pParentNode);
    

Это, я надеюсь, остановит эту ошибку "скалярного удаления деструктора", которая, вероятно, вызвана несовпадением AddRef()/Release().

В любом случае, попробуйте выше и посмотрите, является ли pParentElement нулевым или нет. Если это так, то следующее, что я бы предложил, - это вызвать get_nodeType() для pParentNode, чтобы увидеть, какой это на самом деле узел. Это может дать подсказку о том, что XPath не возвращает то, что вы ожидаете.

CComPtr необходимо, иначе было бы исключение:

объект типа абстрактного класса IXMLDOMNamedNodeMap не разрешено

Другие вопросы по тегам