ちなみに読み込みたいXMLはこんな感じです。(最初なので簡単なところから...)
<sample>
<config name="A" type="1" />
<config name="B" type="2" />
<config name="C" type="3" />
</sample>SDKのMailSetサンプルでXMLを読んでいる部分があったので参考にしてみます。
(と言うよりほとんどそのままです)
まずは サンプルで多様しているオブジェクト開放のマクロを拝借。
#define RELEASE_OBJ(s) \
if (s != NULL) \
{ \
s->Release(); \
s = NULL; \
}続いてXMLの読み込み部分。
わかりにくくなるのでエラー処理をバッサリ切り捨てたらこんな感じになりました。
#define XML_FILE_NAME _T("\\sample.xml")
#define ROOT_ELEMENT_NAME _T("sample")
#define CONFIG_ELEMENT_NAME _T("config")
#define NAME_ATTRIBUTE_NAME _T("name")
#define TYPE_ATTRIBUTE_NAME _T("type")
// XMLファイルの読み込み
static HRESULT LoadXML()
{
HRESULT hr = S_OK;
IXMLDOMDocument *pDom = NULL;
IXMLDOMNode *pTopNode = NULL,
*pConfigNode = NULL,
*pSibling = NULL;
IXMLDOMNamedNodeMap *pNodeMap = NULL;
CLSID clsid = {0};
VARIANT vt = {0};
VARIANT_BOOL vbSuccess = 0;
BSTR bstrName = NULL;
PTCHAR pszName = NULL,
pszType = NULL;
TCHAR szMessage[256] = _T("");
// COMの初期化
CoInitializeEx(NULL, 0);
// XML DOM読み込み
hr = CLSIDFromProgID(_T("Msxml2.DOMDocument"), &clsid);
hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (LPVOID *) &pDom);
// XMLファイル読み込み
vt.vt = VT_BSTR;
vt.bstrVal = SysAllocString(XML_FILE_NAME);
hr = pDom->load(vt, &vbSuccess);
// ルート要素を取得
hr = pDom->selectSingleNode(ROOT_ELEMENT_NAME, &pTopNode);
// ルートノードの子要素の集合を取得
hr = pTopNode->get_firstChild(&pConfigNode);
while (pConfigNode) {
// 子要素の名前を取得
hr = pConfigNode->get_nodeName(&bstrName);
if (!lstrcmpi(bstrName, CONFIG_ELEMENT_NAME)) {
// <config>要素の場合は "name"属性と "type"属性の値を取得
RELEASE_OBJ(pNodeMap);
hr = pConfigNode->get_attributes(&pNodeMap);
pszName = ReadNodeString(pNodeMap, NAME_ATTRIBUTE_NAME);
pszType = ReadNodeString(pNodeMap, TYPE_ATTRIBUTE_NAME);
//
wsprintf(szMessage, _T("name=%s : type=%s"), pszName, pszType);
MessageBox(NULL, szMessage, _T("XML読み込みテスト"), MB_OK);
free(pszName);
free(pszType);
//
}
SysFreeString(bstrName);
// 次の要素を選択
hr = pConfigNode->get_nextSibling(&pSibling);
pConfigNode->Release();
pConfigNode = pSibling;
}
// 後始末系
if (pszName) free(pszName);
if (pszType) free(pszType);
RELEASE_OBJ(pSibling);
RELEASE_OBJ(pConfigNode);
RELEASE_OBJ(pTopNode);
RELEASE_OBJ(pNodeMap);
RELEASE_OBJ(pDom);
VariantClear(&vt);
CoUninitialize();
return hr;
}
// 指定された属性の値を読み込む
static LPTSTR ReadNodeString(IXMLDOMNamedNodeMap *pNodeMap, TCHAR *pszNodeName)
{
HRESULT hr = S_OK;
IXMLDOMNode *pAttlibute = NULL;
VARIANT vt = {0};
size_t cch = 0;
TCHAR *pszRet = NULL;
// 指定された属性の値を読み込む
hr = pNodeMap->getNamedItem(pszNodeName, &pAttlibute);
VariantInit(&vt);
hr = pAttlibute->get_nodeValue(&vt);
// 読み込んだ値をTCHARに変換
// (CString使えばもっと簡単?)
hr = StringCchLength(vt.bstrVal, STRSAFE_MAX_CCH, &cch);
pszRet = (PTCHAR)malloc(sizeof(TCHAR) * (++cch));
StringCchCopy(pszRet, cch, vt.bstrVal);
RELEASE_OBJ(pAttlibute);
VariantClear(&vt);
return pszRet;
}エラー処理を省いて大分見通しが良くなりましたが、それでも見慣れない型が多いですね。
とりあえず COMのの使用開始・終了に CoInitializeEx(), CoUninitialize()、 BSTRの生成・破棄に SysAllocString(), SysFreeString()、 VARIANTの初期化、クリアに VariantInit(), VariantClear()といったあたりを押さえておけばなんとかなるのでしょうか...。
0 件のコメント:
コメントを投稿