I'm building an XML DOM document in C++. My problem is this: I execute an XPATH query from an Element in my Document, which I know will return another Element. The elementPtr->selectSingleNode call returns an IXMLDOMNode. How can I gain access to the attributes of this node?
Part of me wants to downcast the Node to an Element, but I couldn't get the cast to work.
I tried
MSXML2::IXMLDOMElementPtr pParentElement;
pParentNode->QueryInterface(__uuidof(MSXML2::IXMLDOMElement),
(void**) &pParentElement);
Which results in the following runtime error:
0x0057cc58 _com_error::`scalar deleting destructor'(unsigned int)
The other route I tried was to just use nodes:
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;
This fails at "parentNode->get_attributes()".
It seems like I'm missing something; the API should not be this hard to use.
--edit--
What I was missing was that the selectSingleNode call was failing, leaving me with a NULL pointer. You can't call QueryInterface on that, neither can you call get_attributes on it :P
I've selected the answer that fits the question that I asked, not the answer that helped me to realise that I asked the wrong question.
I don't see anything wrong with what you have written.
The smart com pointers will help you convert if they can, you don't have to write the query interface yourself.
MSXML2::IXMLDOMNodePtr pParentNode = pParameterElement->selectSingleNode("parent");
MSXML2::IXMLDOMElementPtr pParentElement( pParentNode );
Using the Ptr types is a bit painfull in my opinion, though the MSXML interface favours them. Here is an equivelant example using ATL
CComPtr<IXMLDOMNode> node = ...;
CComQIPtr<IXMLDOMElement> elementNode( node );
if( elementNode ) {
// it was an element!
} else {
// it's something else try again?
}
The other attempt would look like...
CComPtr<IXMLDOMNamedNodeMap> attributes;
node->get_attributes( &attributes );
if( attributes ) {
_bstr_t name( L"category" );
attributes->getNamedItem(name);
}
And it's COM, it's always hard to use in C++ :(