Как я могу получить доступ к атрибутам элемента из 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
не разрешено