nlib
exi/simple1/simple1.cpp

名前空間のないXMLを読み書きするサンプルです。

自分で何らかのXMLを作成する場合、大抵は名前空間なしで事足りるはずです。 サンプルではXMLの基本的な読み書きについて説明されています。

#include <wchar.h>
#include <map>
#include <string>
#include "nn/nlib/StrTo.h"
using nlib_ns::exi::ExiAllocator;
using nlib_ns::exi::ExiAllocatorEx;
using nlib_ns::exi::XmlStreamReader;
using nlib_ns::exi::XmlStreamWriter;
using nlib_ns::exi::XmlStreamReaderSettings;
using nlib_ns::exi::XmlStreamWriterSettings;
#define N(x) NLIB_EXI_LITERAL(x)
#define M(x) NLIB_EXI_UTF8(x)
// Reads and writes XML in UTF-8 instead of binary if USE_TEXT is defined.
// #define USE_TEXT
const int BUF_SIZE = 1024 * 64;
unsigned char g_WriterBuf[BUF_SIZE];
unsigned char g_ReaderBuf[BUF_SIZE];
const int DATABUF_SIZE = 1024;
unsigned char g_DataBuf[DATABUF_SIZE];
struct CityInfo {
const ExiChar* url;
const ExiChar* governor;
int population;
};
bool SampleExec() {
nlib_printf("Write and Read an XML without xmlnamespace\n\n");
// Use a per-object allocator here.
ExiAllocatorEx al_writer;
if (!al_writer.Initialize(g_WriterBuf, BUF_SIZE)) return false;
MemoryOutputStream os(g_DataBuf, DATABUF_SIZE);
// Construct a bianry/text XML writer in default settings.
// By default, comments and PIs are not written,
// and the prefixes for XML namespace are defined by system.
//
// XmlStreamWriter object is constructed on the memory from the allocator 'al_writer'.
XmlStreamWriterSettings wsettings;
#ifndef USE_TEXT
wsettings.processor = nlib_ns::exi::XML_PROCESSOR_EXI;
#else
wsettings.processor = nlib_ns::exi::XML_PROCESSOR_TEXT;
#endif
UniquePtr<XmlStreamWriter> w(XmlStreamWriter::Create(&os, wsettings, al_writer));
if (!w.get()) return false;
w->WriteStartDocument();
w->WriteStartElement(N("cities"));
w->WriteStartElement(N("city"));
w->WriteAttribute(N("name"), N("Tokyo"));
w->WriteStartElement(N("url"));
w->WriteCharacters(N("http://www.metro.tokyo.jp/"));
w->WriteEndElement();
w->WriteStartElement(N("知事"));
w->WriteCharacters(N("Shintaro Ishihara"));
w->WriteEndElement();
w->WriteStartElement(N("人口"));
w->WriteCharacters(N("13186835"));
w->WriteEndElement();
w->WriteEndElement();
w->WriteStartElement(N("city"));
w->WriteAttribute(N("name"), N("Kyoto"));
w->WriteStartElement(N("url"));
w->WriteCharacters(N("http://www.pref.kyoto.jp/"));
w->WriteEndElement();
w->WriteStartElement(N("知事"));
w->WriteCharacters(N("Keiji Yamada"));
w->WriteEndElement();
w->WriteStartElement(N("人口"));
w->WriteCharacters(N("2633795"));
w->WriteEndElement();
w->WriteEndElement();
w->WriteEndElement();
w->WriteEndDocument();
w->Flush();
// Gets the generated XML.
const void* ptrXml = os.data();
size_t sizeXml = os.Pos();
#ifndef USE_TEXT
const char* format = "Binary XML";
#else
const char* format = "Text XML";
#endif
nlib_printf("%" PRIuS " bytes %s written to the buffer\n", sizeXml, format);
w->Close();
if (w->IsError()) {
nlib_printf("error in writer\n");
return false;
}
w.reset(NULL);
al_writer.Reset(); // You have to reset the allocator.
// Reads the XML written above.
typedef std::map<const ExiChar*, CityInfo> CityDB;
CityDB db;
// Use a per-object allocator here.
ExiAllocatorEx al_reader;
if (!al_reader.Initialize(g_ReaderBuf, BUF_SIZE)) return false;
MemoryInputStream is(ptrXml, sizeXml);
// Construct a bianry/text XML reader in default settings.
// XmlStreamReader object is constructed on the memory from the allocator 'al_reader'.
XmlStreamReaderSettings rsettings;
#ifndef USE_TEXT
rsettings.processor = nlib_ns::exi::XML_PROCESSOR_EXI;
#else
rsettings.processor = nlib_ns::exi::XML_PROCESSOR_TEXT;
#endif
UniquePtr<XmlStreamReader> r(XmlStreamReader::Create(&is, rsettings, al_reader));
if (!r.get()) return false;
const ExiChar* elem = NLIB_EXI_ESTR;
CityInfo* info = NULL;
nlib_printf("Reading the XML from the buffer\n");
// Reads XML by the stream API.
// You can use APIs which is similar to Streaming API for XML(StAX) in Java.
// You don't have to define event handlers which you have to write in SAX programming.
while (r->HasNext()) {
// Gets the XML-parser event one by one.
XmlStreamReader::XmlStreamConstants e = r->Next();
switch (e) {
case XmlStreamReader::START_ELEMENT:
// The string(elem) is valid until XmlStreamReader object is destroyed.
elem = r->GetLocalName();
if (StrCmp(elem, N("city")) == 0) {
info = &db[r->GetAttributeValue(N(""), N("name"))];
}
break;
case XmlStreamReader::CHARACTERS:
if (info) {
if (StrCmp(elem, N("url")) == 0) {
info->url = r->GetText();
} else if (StrCmp(elem, N("知事")) == 0) {
info->governor = r->GetText();
} else if (StrCmp(elem, N("人口")) == 0) {
errno_t err = StrTo(M(r->GetText()), 10, &info->population);
if (err != 0) info->population = 0;
}
}
break;
case XmlStreamReader::START_DOCUMENT:
case XmlStreamReader::END_DOCUMENT:
case XmlStreamReader::END_ELEMENT:
// Do nothing in this sample.
break;
default:
break;
}
}
if (r->IsError()) {
nlib_printf("error in reader\n");
return false;
}
ConsoleOutputStream out_;
TextWriter out;
out.Init(&out_);
CityDB::const_iterator it;
for (it = db.begin(); it != db.end(); ++it) {
out.WriteFormat("%s: \n", M(it->first));
out.WriteFormat("\turl: %s\n", M(it->second.url));
out.WriteFormat("\tgovernor: %s\n", M(it->second.governor));
out.WriteFormat("\tpopulation: %d\n", it->second.population);
}
return true;
}
bool SampleMain(int, char**) {
// no global allocator used in this sample
NLIB_ASSERT(!ExiAllocator::GetAllocator());
bool result = SampleExec();
// no global allocator used in this sample
NLIB_ASSERT(!ExiAllocator::GetAllocator());
return result;
}
NLIB_MAINFUNC