XmlLite は、XML を書き込むためにストリームを使用します。 以下に示すのは、ファイルのストリームへ XML を書き込む例と、メモリのストリームへ XML を書き込む例です。
次に示すのは、ファイルのストリームへ XML を書き込む例です。プログラムと同じフォルダに sample.xml というファイルを作成します。
// stdafx.h #pragma once #include "targetver.h" #define WIN32_LEAN_AND_MEAN #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS #include <atlbase.h> // CComPtrを使用するため #include <xmllite.h> #pragma comment(lib, "xmllite.lib")
// SampleProject.cpp #include "stdafx.h" void Run() { CComPtr<IXmlWriter> pWriter; if(FAILED(CreateXmlWriter(__uuidof(IXmlWriter), reinterpret_cast<void**>(&pWriter), 0))){ MessageBox(NULL, _T("CreateXmlWriter失敗"), _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_CREATE | STGM_WRITE, &pStream))){ MessageBox(NULL, _T("SHCreateStreamOnFile失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pWriter->SetOutput(pStream))){ MessageBox(NULL, _T("SetOutput失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } // インデント有効化 if(FAILED(pWriter->SetProperty(XmlWriterProperty_Indent, TRUE))){ MessageBox(NULL, _T("SetProperty失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } // <?xml version="1.0" encoding="UTF-8"?> if(FAILED(pWriter->WriteStartDocument(XmlStandalone_Omit))){ MessageBox(NULL, _T("WriteStartDocument失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } // <sample> if(FAILED(pWriter->WriteStartElement(NULL, L"sample", NULL))){ MessageBox(NULL, _T("WriteStartElement失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } // <requirement> // <type>ヘッダ</type> // <name>XmlLite.h</name> // </requirement> if(FAILED(pWriter->WriteStartElement(NULL, L"requirement", NULL))){ MessageBox(NULL, _T("WriteStartElement失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pWriter->WriteElementString(NULL, L"type", NULL, L"ヘッダ"))){ MessageBox(NULL, _T("WriteElementString失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pWriter->WriteElementString(NULL, L"name", NULL, L"XmlLite.h"))){ MessageBox(NULL, _T("WriteElementString失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pWriter->WriteFullEndElement())){ MessageBox(NULL, _T("WriteFullEndElement失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } // <requirement> // <type>ライブラリ</type> // <name>XmlLite.lib</name> // </requirement> if(FAILED(pWriter->WriteStartElement(NULL, L"requirement", NULL))){ MessageBox(NULL, _T("WriteStartElement失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pWriter->WriteElementString(NULL, L"type", NULL, L"ライブラリ"))){ MessageBox(NULL, _T("WriteElementString失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pWriter->WriteElementString(NULL, L"name", NULL, L"XmlLite.lib"))){ MessageBox(NULL, _T("WriteElementString失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pWriter->WriteFullEndElement())){ MessageBox(NULL, _T("WriteFullEndElement失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } // 自動的に<sample>が閉じられる if(FAILED(pWriter->WriteEndDocument())){ MessageBox(NULL, _T("WriteEndDocument失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pWriter->Flush())){ MessageBox(NULL, _T("Flush失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } MessageBox(NULL, _T("完了"), _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; }
まず、stdafx.h ヘッダでは、ATL の CComPtr を使用するために atlbase.h ヘッダをインクルードします。 また、XmlLite を使用するために xmllite.h ヘッダをインクルードし、#pragma ディレクティブで xmllite.lib をリンクします。
_tWinMain() から呼び出される Run() では、まず、CreateXmlWriter() を呼び出して IXmlWriter インターフェイスの実装を取得します。 CreateXmlWriter() の第1引数はインターフェイスID、第2引数は IXmlWriter のスマートポインタへのポインタ、 第3引数はユーザがメモリ割り当てを制御するための IMalloc 実装へのポインタです。
次に、SHCreateStreamOnFile() を呼び出して書き込み用のファイルストリームを作成し、 IXmlWriter::SetOutput() を呼び出してファイルストリームを関連付けます。
次に、引数として XmlWriterProperty_Indent を指定して IXmlWriter::SetProperty() を呼び出すことによって、 書き込む XML に自動的にインデントを追加します。
次に、IXmlWriter::WriteStartDocument() を呼び出して XML ファイルに XML 宣言を書き込みます。 この際、エンコードはデフォルトで UTF-8 が指定されます。
次に、XML の要素とテキストを書き込みます。IXmlWriter::WriteStartElement() は要素の開始タグを書き込み、 IXmlWriter::WriteFullEndElement() は要素の終了タグを書き込みます。 IXmlWriter::WriteElementString() は要素とテキストを同時に書き込みます。
次に、IXmlWriter::WriteEndDocument() を呼び出します。この呼び出しによって、 閉じられていない要素(今回の例では <sample> )が自動的に閉じられます。
最後に、IXmlWriter::Flush() を呼び出してバッファの内容を確実にストリームに書き込みます。 以下に示すのが、作成される 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>
次に示すのは、先述のプログラムを変更してメモリのストリームへ XML を書き込む例です。 書き込んだ XML を文字列としてメッセージボックスに表示します。
// 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<IXmlWriter> pWriter; if(FAILED(CreateXmlWriter(__uuidof(IXmlWriter), reinterpret_cast<void**>(&pWriter), 0))){ MessageBox(NULL, _T("CreateXmlWriter失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } // XML用メモリ割り当て HGLOBAL hXml = GlobalAlloc(GMEM_MOVEABLE, 0); // メモリストリーム作成 CComPtr<IStream> pStream; if(FAILED(CreateStreamOnHGlobal(hXml, TRUE, &pStream))){ MessageBox(NULL, _T("CreateStreamOnHGlobal失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pWriter->SetOutput(pStream))){ MessageBox(NULL, _T("SetOutput失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } // インデント有効化 if(FAILED(pWriter->SetProperty(XmlWriterProperty_Indent, TRUE))){ MessageBox(NULL, _T("SetProperty失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } // <?xml version="1.0" encoding="UTF-8"?> if(FAILED(pWriter->WriteStartDocument(XmlStandalone_Omit))){ MessageBox(NULL, _T("WriteStartDocument失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } // <sample> if(FAILED(pWriter->WriteStartElement(NULL, L"sample", NULL))){ MessageBox(NULL, _T("WriteStartElement失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } // <requirement> // <type>ヘッダ</type> // <name>XmlLite.h</name> // </requirement> if(FAILED(pWriter->WriteStartElement(NULL, L"requirement", NULL))){ MessageBox(NULL, _T("WriteStartElement失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pWriter->WriteElementString(NULL, L"type", NULL, L"ヘッダ"))){ MessageBox(NULL, _T("WriteElementString失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pWriter->WriteElementString(NULL, L"name", NULL, L"XmlLite.h"))){ MessageBox(NULL, _T("WriteElementString失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pWriter->WriteFullEndElement())){ MessageBox(NULL, _T("WriteFullEndElement失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } // <requirement> // <type>ライブラリ</type> // <name>XmlLite.lib</name> // </requirement> if(FAILED(pWriter->WriteStartElement(NULL, L"requirement", NULL))){ MessageBox(NULL, _T("WriteStartElement失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pWriter->WriteElementString(NULL, L"type", NULL, L"ライブラリ"))){ MessageBox(NULL, _T("WriteElementString失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pWriter->WriteElementString(NULL, L"name", NULL, L"XmlLite.lib"))){ MessageBox(NULL, _T("WriteElementString失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pWriter->WriteFullEndElement())){ MessageBox(NULL, _T("WriteFullEndElement失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } // 自動的に<sample>が閉じられる if(FAILED(pWriter->WriteEndDocument())){ MessageBox(NULL, _T("WriteEndDocument失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pWriter->Flush())){ MessageBox(NULL, _T("Flush失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } // UTF-8のXML文字列を取得 LPCSTR utf8Xml = reinterpret_cast<LPCSTR>(GlobalLock(hXml)); // メッセージボックスに表示するためにXML文字列をUTF-8からUTF-16へ変換 int size = MultiByteToWideChar(CP_UTF8, 0, utf8Xml, -1, NULL, 0); WCHAR* utf16Xml = new WCHAR[size]; MultiByteToWideChar(CP_UTF8, 0, utf8Xml, -1, utf16Xml, size); CString result = utf16Xml; delete[] utf16Xml; GlobalUnlock(hXml); 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; }
まず、stdafx.h ヘッダでは、ATL の CString を使用するために atlstr.h ヘッダをインクルードします。
次に、ストリームを作成する部分を変更します。まず、GlobalAlloc() を呼び出してサイズ 0 のメモリを割り当て、 CreateStreamOnHGlobal() を呼び出してメモリストリームを作成します。 なお、割り当てるメモリの初期サイズは 0 ですが、データを書き込むと自動的に拡張されます。 また、CreateStreamOnHGlobal() の第2引数に TRUE を指定しているため、ストリームが解放されるタイミングで、 割り当てたメモリも自動的に解放されます。
最後に、XML をメモリストリームに書き込んだ後に、GlobalLock() を呼び出して XML を取得します。 この際、取得する XML のエンコードはデフォルトで UTF-8 です。 なお、このまま取得した XML をメッセージボックスに表示すると、 プロジェクトを Unicode ビルドした場合に文字化けしてしまいます。 (Unicode ビルドしたプロジェクトのエンコードは UTF-16 です。) そのため、今回の例ではメッセージボックスに表示する前に UTF-16 へ変換します。