nlib
exi/simple2/simple2.cpp

名前空間プレフィックスを保持したりコメントのついたXMLを読み書きするサンプルです。

名前空間つきのXMLを読み書きしています。 名前空間プレフィックス名をバイナリXML内に含めるにはXmlStreamWriterSettingsをデフォルトから変更してXmlStreamWriterを作成する必要があることに注意してください。

/*--------------------------------------------------------------------------------*
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 <string>
using nlib_ns::exi::ExiAllocator;
using nlib_ns::exi::ExiAllocatorEx;
using nlib_ns::exi::XmlStreamReader;
using nlib_ns::exi::XmlStreamReaderSettings;
using nlib_ns::exi::XmlStreamWriter;
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_readerbuf[kBufSize];
unsigned char g_writerbuf[kBufSize];
const int kDataBufSize = 1024;
unsigned char g_data_buf[kDataBufSize];
bool WriteXml() {
ExiAllocatorEx al;
if (al.Init(g_writerbuf, kBufSize) != 0) return false;
MemoryOutputStream os(g_data_buf, kDataBufSize);
// You can specify encode options via XmlStreamWriterSettings.
XmlStreamWriterSettings settings;
#ifndef USE_TEXT
// '$EXI' will be written in the beginning of the binary if encodeCookie is true.
settings.encodeCookie = true;
// XmlStreamReader can detect encode options specified here if encodeOptions is true.
// You don't have to set XmlStreamReaderSettings when reading.
settings.encodeOptions = true;
// XML comment(<!-- ... -->) is written if preserve.comments is true.
settings.preserve.comments = true;
// User specified names of prefixes are encoded if preserve.prefixes is true.
// Otherwise, the names are defined by system.
settings.preserve.prefixes = true;
#else
// The settings above are not valid if you read XML in text(UTF-8).
settings.processor = nlib_ns::exi::XML_PROCESSOR_TEXT;
#endif
UniquePtr<XmlStreamWriter> w(XmlStreamWriter::Create(&os, settings, al));
if (!w.get()) return false;
// <root>
// <e attr0="value0" attr1="value1" pfx:attr2="value2" xmlns:pfx="http://example.com"/>
// <!--comment-->
// <pfx:e xmlns:pfx="http://example.com">
// <pfx:c/>
// <c/>
// <c xmlns="http://example.com"/>
// <pfx:c xmlns:pfx="http://example.com/2"/>
// </pfx:e>
// <e xmlns="http://example.com/defaultns" att="value">
// <c/>
// <c xmlns=""/>
// </e>
// <pfx:e xmlns:pfx="http://example.com" xmlns:pfx2="http://example.com/2">
// <pfx2:e/>
// </pfx:e>
// </root>
w->WriteStartDocument();
w->WriteStartElement(N("root"));
{
//
// <e attr0="value0" attr1="value1" pfx:attr2="value2" xmlns:pfx="http://example.com"/>
//
w->WriteStartElement(N("e"));
// Omits URI and prefix. no namespace is used.
w->WriteAttribute(N("attr0"), N("value0"));
// Same as the previous one.
w->WriteAttribute(N(""), N(""), N("attr1"), N("value1"));
// Writes the attribute with XML namespace.
w->WriteAttribute(N("pfx"), N("http://example.com"), N("attr2"), N("value2"));
w->WriteEndElement();
}
{
//
// <!--comment-->
//
// You have to enable preserve.comments in XmlStreamWriterSettings
// if you write XML comments.
// Otherwise, no XML comments will be written.
w->WriteComment(N("comment"));
}
{
// <pfx:e xmlns:pfx="http://example.com">
// <pfx:c/>
// <c/>
// <c xmlns="http://example.com"/>
// <pfx:c xmlns:pfx="http://example.com/2"/>
// </pfx:e>
// Automatically generates XML namespace declaration if there is no previous declaration.
w->WriteStartElement(N("pfx"), N("http://example.com"), N("e"));
w->WriteEmptyElement(N("pfx"), N("http://example.com"), N("c"));
// Writes an element with no XML namespace.
w->WriteEmptyElement(N("c"));
// Writes an element with default XML namespace.
w->WriteEmptyElement(N(""), N("http://example.com"), N("c"));
// Overrides the prefix for another URI.
w->WriteEmptyElement(N("pfx"), N("http://example.com/2"), N("c"));
w->WriteEndElement();
}
{
// <e xmlns="http://example.com/defaultns" att="value">
// <c/>
// <c xmlns=""/>
// </e>
// Declares the default namespace if NULL or "" is specified for prefix.
w->WriteStartElement(N(""), N("http://example.com/defaultns"), N("e"));
// Default XML namespace is not valid on attributes.
// The attribute without XML namespace is written.
w->WriteAttribute(N("att"), N("value"));
// Writes the element with default XML namespace.
w->WriteEmptyElement(N(""), N("http://example.com/defaultns"), N("c"));
// Resets the default XML namespace, and the elements with no XML namespace is written.
w->WriteEmptyElement(N("c"));
w->WriteEndElement();
}
{
// <pfx:e xmlns:pfx="http://example.com" xmlns:pfx2="http://example.com/2">
// <pfx2:e/>
// </pfx:e>
w->WriteStartElement(N("pfx"), N("http://example.com"), N("e"));
// You can also declare an XML namespace by WriteNamespace().
w->WriteNamespace(N("pfx2"), N("http://example.com/2"));
// XML namespace declaration is not performed
// because the same XML namespace is declared at the parent element.
w->WriteEmptyElement(N("pfx2"), N("http://example.com/2"), N("e"));
w->WriteEndElement();
}
w->WriteEndElement();
w->WriteEndDocument();
w->Close();
return !!*w;
}
class SimplePrinter {
int indent;
XmlStreamReader* r;
ConsoleOutputStream out_;
TextWriter out;
public:
explicit SimplePrinter(XmlStreamReader* reader) : indent(0), r(reader) {
out.Init();
out.Open(&out_);
}
void Indent() {
for (int i = 0; i < indent; ++i) {
out.Write(" ");
}
}
void Print();
};
void SimplePrinter::Print() {
// Prints XML like tagged text.
while (r->HasNext()) {
switch (r->Next()) {
case XmlStreamReader::START_ELEMENT: {
const ExiChar* prefix;
const ExiChar* uri;
Indent();
// URIs for local names are also written.
prefix = r->GetPrefix();
uri = r->GetNamespaceUri();
if (uri[0] == '\0')
out.WriteFormat("<%s", M(r->GetLocalName()));
else
out.WriteFormat("<%s(%s):%s", M(prefix), M(r->GetNamespaceUri()),
M(r->GetLocalName()));
// Outputs XML namespace declaration
{
// num_ns >= 1 if XML namespaces are declared.
size_t num_ns = r->GetNamespaceCount();
size_t i;
for (i = 0; i < num_ns; ++i) {
prefix = r->GetNamespacePrefix(i);
if (prefix[0] == '\0') {
// Default XML namespace. prefix is empty string.
out.WriteFormat(" xmlns=\"%s\"", M(r->GetNamespaceUri(i)));
} else {
out.WriteFormat(" xmlns:%s=\"%s\"", M(prefix), M(r->GetNamespaceUri(i)));
}
}
}
// Outputs XML attributes
{
size_t num_att = r->GetAttributeCount();
size_t i;
for (i = 0; i < num_att; ++i) {
// Note that the order of the attributes is arbitrary in XML.
prefix = r->GetAttributePrefix(i);
uri = r->GetAttributeNamespaceUri(i);
if (uri[0] == '\0') {
out.WriteFormat(" %s=\"%s\"", M(r->GetAttributeLocalName(i)),
M(r->GetAttributeValue(i)));
} else {
out.WriteFormat(" %s(%s):%s=\"%s\"", M(prefix), M(uri),
M(r->GetAttributeLocalName(i)), M(r->GetAttributeValue(i)));
}
}
}
out.Write(">\n");
++indent;
} break;
case XmlStreamReader::END_ELEMENT: {
const ExiChar* prefix;
--indent;
Indent();
prefix = r->GetPrefix();
if (prefix[0] == '\0') {
out.WriteFormat("</%s>\n", M(r->GetLocalName()));
} else {
out.WriteFormat("</%s:%s>\n", M(prefix), M(r->GetLocalName()));
}
} break;
case XmlStreamReader::COMMENT:
Indent();
// In the case of XML comment,
// the string returned by r->GetText() becomes invalid after r->Next() is called.
// You have to copy the string if you use later.
out.WriteFormat("<!--%s-->\n", M(r->GetText()));
break;
default:
break;
}
}
}
bool ReadXml() {
ExiAllocatorEx al;
if (al.Init(g_readerbuf, kBufSize) != 0) return false;
MemoryInputStream is(g_data_buf, kDataBufSize);
XmlStreamReaderSettings settings;
#ifndef USE_TEXT
// The settings in the binary XML is used if encodeOption is true in it.
// Reads XML comments enabled binary if preserve.comments is true.
// settings.preserve.comments = true;
// Reads prefix encoding enabled binary if preserve.prefixes is true.
// settings.preserve.prefixes = true;
#else
settings.processor = nlib_ns::exi::XML_PROCESSOR_TEXT;
#endif
UniquePtr<XmlStreamReader> r(XmlStreamReader::Create(&is, settings, al));
if (!r.get()) return false;
SimplePrinter printer(r.get());
printer.Print();
return !!*r;
}
bool SampleMain(int, char**) {
// no global allocator used in this sample
NLIB_ASSERT(!ExiAllocator::GetAllocator());
nlib_printf("Write and Read an XML with xmlnamespace\n\n");
bool result = WriteXml() && ReadXml();
// no global allocator used in this sample
NLIB_ASSERT(!ExiAllocator::GetAllocator());
return result;
}
NLIB_MAINFUNC