[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