167 lines
4.6 KiB
C++
167 lines
4.6 KiB
C++
// QueryNodes.cpp : Defines the entry point for the console application.
|
|
//
|
|
|
|
#include <stdio.h>
|
|
#include <msxml6.h>
|
|
|
|
#pragma warning(disable : 4127) // conditional expression is constant
|
|
// Macro that calls a COM method returning HRESULT value.
|
|
#define CHK_HR(stmt) do { hr=(stmt); if (FAILED(hr)) goto CleanUp; } while(0)
|
|
|
|
// Macro to verify memory allcation.
|
|
#define CHK_ALLOC(p) do { if (!(p)) { hr = E_OUTOFMEMORY; goto CleanUp; } } while(0)
|
|
|
|
// Macro that releases a COM object if not NULL.
|
|
#define SAFE_RELEASE(p) do { if ((p)) { (p)->Release(); (p) = NULL; } } while(0)
|
|
|
|
// Helper function to create a VT_BSTR variant from a null terminated string.
|
|
HRESULT VariantFromString(PCWSTR wszValue, VARIANT &Variant)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BSTR bstr = SysAllocString(wszValue);
|
|
CHK_ALLOC(bstr);
|
|
|
|
V_VT(&Variant) = VT_BSTR;
|
|
V_BSTR(&Variant) = bstr;
|
|
|
|
CleanUp:
|
|
return hr;
|
|
}
|
|
|
|
// Helper function to create a DOM instance.
|
|
HRESULT CreateAndInitDOM(IXMLDOMDocument **ppDoc)
|
|
{
|
|
HRESULT hr = CoCreateInstance(__uuidof(DOMDocument60), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(ppDoc));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// these methods should not fail so don't inspect result
|
|
(*ppDoc)->put_async(VARIANT_FALSE);
|
|
(*ppDoc)->put_validateOnParse(VARIANT_FALSE);
|
|
(*ppDoc)->put_resolveExternals(VARIANT_FALSE);
|
|
(*ppDoc)->put_preserveWhiteSpace(VARIANT_TRUE);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
// Helper function to display parse error.
|
|
// It returns error code of the parse error.
|
|
HRESULT ReportParseError(IXMLDOMDocument *pDoc, _Null_terminated_ const WCHAR* pwszDesc)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HRESULT hrRet = E_FAIL; // Default error code if failed to get from parse error.
|
|
IXMLDOMParseError *pXMLErr = NULL;
|
|
BSTR bstrReason = NULL;
|
|
|
|
CHK_HR(pDoc->get_parseError(&pXMLErr));
|
|
CHK_HR(pXMLErr->get_errorCode(&hrRet));
|
|
CHK_HR(pXMLErr->get_reason(&bstrReason));
|
|
wprintf(L"%s\n%s\n", pwszDesc, bstrReason);
|
|
|
|
CleanUp:
|
|
SAFE_RELEASE(pXMLErr);
|
|
SysFreeString(bstrReason);
|
|
return hrRet;
|
|
}
|
|
|
|
HRESULT queryNodes()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IXMLDOMDocument *pXMLDom = NULL;
|
|
IXMLDOMNodeList *pNodes = NULL;
|
|
IXMLDOMNode *pNode = NULL;
|
|
|
|
BSTR bstrQuery1 = NULL;
|
|
BSTR bstrQuery2 = NULL;
|
|
BSTR bstrNodeName = NULL;
|
|
BSTR bstrNodeValue = NULL;
|
|
VARIANT_BOOL varStatus;
|
|
VARIANT varFileName;
|
|
VariantInit(&varFileName);
|
|
|
|
CHK_HR(CreateAndInitDOM(&pXMLDom));
|
|
|
|
CHK_HR(VariantFromString(L"stocks.xml", varFileName));
|
|
CHK_HR(pXMLDom->load(varFileName, &varStatus));
|
|
if (varStatus != VARIANT_TRUE)
|
|
{
|
|
CHK_HR(ReportParseError(pXMLDom, L"Failed to load DOM from stocks.xml."));
|
|
}
|
|
|
|
// Query a single node.
|
|
bstrQuery1 = SysAllocString(L"//stock[1]/*");
|
|
CHK_ALLOC(bstrQuery1);
|
|
CHK_HR(pXMLDom->selectSingleNode(bstrQuery1, &pNode));
|
|
if (pNode)
|
|
{
|
|
wprintf(L"Result from selectSingleNode:\n");
|
|
CHK_HR(pNode->get_nodeName(&bstrNodeName));
|
|
wprintf(L"Node, <%s>:\n", bstrNodeName);
|
|
SysFreeString(bstrNodeName);
|
|
|
|
CHK_HR(pNode->get_xml(&bstrNodeValue));
|
|
wprintf(L"\t%s\n\n", bstrNodeValue);
|
|
SysFreeString(bstrNodeValue);
|
|
SAFE_RELEASE(pNode);
|
|
}
|
|
else
|
|
{
|
|
CHK_HR(ReportParseError(pXMLDom, L"Error while calling selectSingleNode."));
|
|
}
|
|
|
|
// Query a node-set.
|
|
bstrQuery2 = SysAllocString(L"//stock[1]/*");
|
|
CHK_ALLOC(bstrQuery2);
|
|
CHK_HR(pXMLDom->selectNodes(bstrQuery2, &pNodes));
|
|
if(pNodes)
|
|
{
|
|
wprintf(L"Results from selectNodes:\n");
|
|
//get the length of node-set
|
|
long length;
|
|
CHK_HR(pNodes->get_length(&length));
|
|
for (long i = 0; i < length; i++)
|
|
{
|
|
CHK_HR(pNodes->get_item(i, &pNode));
|
|
CHK_HR(pNode->get_nodeName(&bstrNodeName));
|
|
wprintf(L"Node (%d), <%s>:\n", i, bstrNodeName);
|
|
SysFreeString(bstrNodeName);
|
|
|
|
CHK_HR(pNode->get_xml(&bstrNodeValue));
|
|
wprintf(L"\t%s\n", bstrNodeValue);
|
|
SysFreeString(bstrNodeValue);
|
|
SAFE_RELEASE(pNode);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CHK_HR(ReportParseError(pXMLDom, L"Error while calling selectNodes."));
|
|
}
|
|
|
|
CleanUp:
|
|
SAFE_RELEASE(pXMLDom);
|
|
SAFE_RELEASE(pNodes);
|
|
SAFE_RELEASE(pNode);
|
|
SysFreeString(bstrQuery1);
|
|
SysFreeString(bstrQuery2);
|
|
SysFreeString(bstrNodeName);
|
|
SysFreeString(bstrNodeValue);
|
|
VariantClear(&varFileName);
|
|
|
|
return hr;
|
|
}
|
|
|
|
int __cdecl wmain()
|
|
{
|
|
HRESULT hr = CoInitialize(NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = queryNodes();
|
|
if(FAILED(hr))
|
|
{
|
|
wprintf(L"Failed.\n");
|
|
}
|
|
CoUninitialize();
|
|
}
|
|
return 0;
|
|
|
|
}
|