ちなみに読み込みたい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 件のコメント:
コメントを投稿