nlib
exi/simple1/simple1.cpp

A sample demonstrating reading and writing of XML without a namespace.

When creating some form of XML yourself, you should be OK most of the time without requiring namespaces. The sample explains how to do basic reading and writing of XML.

/*--------------------------------------------------------------------------------*
Project: CrossRoad
Copyright (C)Nintendo All rights reserved.
These coded instructions, statements, and computer programs contain proprietary
information of Nintendo and/or its licensed developers and are protected by
national and international copyright laws. They may not be disclosed to third
parties or copied or duplicated in any form, in whole or in part, without the
prior written consent of Nintendo.
The content herein is highly confidential and should be handled accordingly.
*--------------------------------------------------------------------------------*/
#include <wchar.h>
#include <map>
#include <string>
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 kBufSize = 1024 * 64;
unsigned char g_writerbuf[kBufSize];
unsigned char g_readerbuf[kBufSize];
const int kDataBufSize = 1024;
unsigned char g_data_buf[kDataBufSize];
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 (nlib_is_error(al_writer.Init(g_writerbuf, kBufSize))) return false;
MemoryOutputStream os(g_data_buf, kDataBufSize);
// 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* ptr_xml = os.data();
size_t size_xml = 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", size_xml, format);
w->Close();
if (nlib_is_error(*w)) {
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 (nlib_is_error(al_reader.Init(g_readerbuf, kBufSize))) return false;
MemoryInputStream is(ptr_xml, size_xml);
// 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 = nlib_strto_int32(&info->population, M(r->GetText()), NULL, 10);
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 (nlib_is_error(*r)) {
nlib_printf("error in reader\n");
return false;
}
ConsoleOutputStream out_;
TextWriter out;
out.Init();
out.Open(&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