[xsde-users] Serialization with indentation
Boris Kolpackov
boris at codesynthesis.com
Wed Feb 18 10:20:19 EST 2009
Hi Anatoly,
[CC'ed xsde-users]
Anatoly Borodyansky <aborodya at yahoo.com> writes:
> The issue I'm having is when I'm serializing object using hybrid model,
> there is no line feeds/ hierarchy whatsoever (same happens in streaming
> example) am I missing something, or this is by design?
This is by design. XSD/e is primarily targeted at embedded systems
and provides only essential functionality to minimize size. It is,
however, quite easy to add custom indentation of XML using the
xml_schema::writer interface (see Section 8.1, "Document Serializer"
in the Embedded C++/Serializer Getting Started Guide). Below is an
implementation that I came up with. You would need to "chain" it to an
actual writer which writes to a file or stream (see ostream_write and
ostream_flush functions in libxsde/xsde/cxx/serializer/genx/document.cxx
for an example on how to write to std::ostream).
Boris
struct indenter: xml_schema::writer
{
indenter (xml_schema::writer& next)
: state_ (in_doc), depth_ (0), simple_ (true), next_ (next)
{
}
virtual void
write (const char* s, size_t n)
{
if (state_ == in_doc)
doc (s, n);
else
tag (s, n);
}
virtual void
flush ()
{
next_.flush ();
}
private:
void
doc (const char* s, size_t n)
{
using xml_schema::ro_string;
// Look for the next '<'
//
ro_string str (s, n);
size_t p = str.find ('<');
if (p == ro_string::npos)
{
next_.write (s, n);
return;
}
// Don't write '<'.
//
if (p != 0)
next_.write (s, p);
s += p + 1;
n -= p + 1;
state_ = in_tag;
if (n != 0)
tag (s, n);
}
void
tag (const char* s, size_t n)
{
using xml_schema::ro_string;
// If we don't know what kind of tag we are in, sort it out
// first. Also output newlines and indentation.
//
if (state_ == in_tag)
{
if (*s == '/')
{
s++;
n--;
depth_--;
state_ = in_ctag;
if (!simple_)
indent ();
next_.write ("</", 2);
simple_ = false;
}
else
{
state_ = in_otag;
if (depth_ != 0)
indent ();
next_.write ("<", 1);
depth_++;
simple_ = true;
}
if (n == 0)
return;
}
// Find the end of tag.
//
ro_string str (s, n);
size_t p = str.find ('>');
if (p == ro_string::npos)
{
next_.write (s, n);
return;
}
next_.write (s, p + 1);
s += p + 1;
n -= p + 1;
state_ = in_doc;
if (n != 0)
doc (s, n);
}
void
indent ()
{
next_.write ("\n", 1);
for (size_t i = 0; i < depth_; ++i)
next_.write (" ", 2);
}
private:
enum state
{
in_doc,
in_tag,
in_otag,
in_ctag,
};
state state_;
size_t depth_;
bool simple_;
xml_schema::writer& next_;
};
More information about the xsde-users
mailing list