XmlLite はXML 宣言からエンコードを判断するため、ネイティブでサポートされている UTF-16 の XML を読み込むために特別な処理は必要ありません。
しかしながら、XML 宣言にエンコードが指定されていない場合や、実際のエンコードと異なるエンコードが指定されている場合でも、 プログラム内で明示的にエンコードを指定することで正しく XML を読み込むことができます。 次に示すのは、プログラム内でエンコードを UTF-16 に指定して XML を読み込む例です。 あらかじめ sample.xml というファイルをプログラムと同じフォルダに用意しておき、 XML を読み込んだ結果をメッセージボックスに表示します。 なお、sample.xml の実際のエンコードは UTF-16 ですが、XML 宣言では実際のエンコードとは異なる UTF-8 に指定します。
// sample.xml <?xml version="1.0" encoding="UTF-8"?> <sample> <requirement> <type>ヘッダ</type> <name>XmlLite.h</name> </requirement> <requirement> <type>ライブラリ</type> <name>XmlLite.lib</name> </requirement> </sample>
// stdafx.h #pragma once #include "targetver.h" #define WIN32_LEAN_AND_MEAN #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS #include <atlbase.h> // CComPtrを使用するため #include <atlstr.h> // CStringを使用するため #include <xmllite.h> #pragma comment(lib, "xmllite.lib")
// SampleProject.cpp #include "stdafx.h" void Run() { CComPtr<IXmlReader> pReader; if(FAILED(CreateXmlReader(__uuidof(IXmlReader), reinterpret_cast<void**>(&pReader), 0))){ MessageBox(NULL, _T("CreateXmlReader失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } // XMLファイルパス作成 TCHAR xml[MAX_PATH]; GetModuleFileName(NULL, xml, sizeof(xml) / sizeof(TCHAR)); PathRemoveFileSpec(xml); PathAppend(xml, _T("sample.xml")); // ファイルストリーム作成 CComPtr<IStream> pStream; if(FAILED(SHCreateStreamOnFile(xml, STGM_READ, &pStream))){ MessageBox(NULL, _T("SHCreateStreamOnFile失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } // エンコード指定 CComPtr<IXmlReaderInput> pReaderInput; if(FAILED(CreateXmlReaderInputWithEncodingName(pStream, NULL, L"UTF-16", FALSE, NULL, &pReaderInput))){ MessageBox(NULL, _T("CreateXmlReaderInputWithEncodingName失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pReader->SetInput(pReaderInput))){ MessageBox(NULL, _T("SetInput失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } CString result; LPCWSTR pwszLocalName; LPCWSTR pwszValue; XmlNodeType nodeType; while(S_OK == pReader->Read(&nodeType)){ switch(nodeType){ case XmlNodeType_Element: if(FAILED(pReader->GetLocalName(&pwszLocalName, NULL))){ MessageBox(NULL, _T("GetLocalName失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } break; case XmlNodeType_Text: if(FAILED(pReader->GetValue(&pwszValue, NULL))){ MessageBox(NULL, _T("GetValue失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } CString row; if(lstrcmp(pwszLocalName, _T("type")) == 0){ row.Format(_T("種類:%s\n"), pwszValue); }else if(lstrcmp(pwszLocalName, _T("name")) == 0){ row.Format(_T("名前:%s\n\n"), pwszValue); } result += row; break; } } MessageBox(NULL, result, _T("結果"), MB_OK | MB_ICONINFORMATION); } int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); Run(); return 0; }
XML を読み込む際のエンコードを指定するためには、まず、CreateXmlReaderInputWithEncodingName() を呼び出します。 引数は順に、ストリームへのポインタ、ユーザがメモリ割り当てを制御するための IMalloc 実装へのポインタ、 エンコード名、エンコード名をヒントとして利用するかどうかのフラグ、外部エンティティの解決に使用されるベース URI、 入力オブジェクトを示す IXmlReaderInput のスマートポインタへのポインタです。 次に、IXmlReader::SetInput() を呼び出して入力オブジェクトを関連付けます。
このように、CreateXmlReaderInputWithEncodingName() を使用することで、 sample.xml の XML 宣言には実際のエンコードとは異なる UTF-8 が指定されているにも関わらず、 正しいエンコードである UTF-16 で読み込むことができます。