NAME

Doc::Perlish::Data - Data structures as Perldoc streams

DESCRIPTION

The unlucky of us have to, at some point, try to shoe-horn their data objects into a document structure not designed for serialisation. Of course, you can do this with Doc::Perlish.

To send a message, you point Doc::Perlish::Data::Chill at a data structure. This structure currently should contain no circular references; currently they are detected, and error processing instructions inserted into the event stream when they are found again. Fixing this properly requires the marshalling system to remember the entire data structure it has sent, which isn't good if you're dealing with very large data structures that might themselves be lazily streaming from a database or some such.

The Doc::Perlish::Data::Chill class acts as a Perldoc::Sender; so to actually write a document, you should connect it to a writer class, such as Doc::Perlish::Writer::XML.

Here is an example of using this interface;

my $chiller = Doc::Perlish::Data::Chill->new(source => $structure);
my $writer  = Doc::Perlish::Writer::XML->new(output => "somefile.xml");
$chiller->receiver($writer);
$chiller->send_all;

Doc::Perlish::Data::Chill provides per-class hooks for controlling the document marshalling; these are described on its man page.

Going the other way is a matter of connecting a stream of Doc::Perlish events to Doc::Perlish::Data::Thaw. This would normally come from a source such as a Doc::Perlish::Parser::XML;

my $reader = Doc::Perlish::Reader->new(input => "source.xml");
my $parser = Doc::Perlish::Parser::XML->new(reader => $reader);
my $warmer = Doc::Perlish::Data::Thaw->new();
$parser->receiver($warmer);
$reader->send_all();

Doc::Perlish::Data XML FORM

XML Data is nasty, but we're talking about a document structure here, so XML is a good way to describe it.

Scalars

All scalars are represented as a stream of characters. There is nothing at present to determine what data type they represent, other than context.

For example, the scalar "Foo", is represented as:

Foo
Sets, Arrays and Hashes

Sets (well, actually only Set::Object containers) are represented identically to arrays.

The special tag <item> is used to denote an entry in an array or a hash. It may have one attribute; name, if it is an entry in a hash.

For instance, this hash:

{ "foo" => "bar",
  "baz" => "frop",
}

Would be represented as:

<item name="foo">bar</item>
<item name="baz">frop</item>

If you are passing the document in to Doc::Perlish::Data::Thaw, you can use, if it makes you feel better:

<Hash>
  <item name="foo">bar</item>
  <item name="baz">frop</item>
</Hash>

Arrays are a similar story; this array:

[ "one", "two", [ "three part 1", "three part 2" ] ]

Would be represented as:

<item>one</item>
<item>two</item>
<item>
  <item>three part 1</item>
  <item>three part 2</item>
</item>

Or, if you wanted to be more explicit about where the collections are;

<Array>
  <item>one</item>
  <item>two</item>
  <item>
    <Array>
      <item>three part 1</item>
      <item>three part 2</item>
    </Array>
  </item>
</Array>

It is currently possible to have Doc::Perlish::Data::Chill insert these extra tags, but still untested.

blessed objects

Objects (apart from Set::Object containers) are converted to an element, with attributes for properties and sub-elements for complex properties.

For instance, the following Perl object;

bless({ Foo => "bar",
        Baz => "frop",
        Cheese => bless({ jeez => "louise" }, "Bert"),
      }, "Bob");

Would be represened in YAML as the simple;

--- !perl/Bob
Baz: frop
Cheese: !perl/Bert
  jeez: louise
Foo: bar

But this isn't a document about how easy it is to send data structures around using YAML. No, in our little XML language it looks like this:

<Bob Baz="frop" Foo="bar">
  <Cheese>
    <Bert jeez="louise"/>
  </Cheese>
</Bob>

This is actually converted to the following Perl structure on reassembly;

Bob->new( Baz => "frop", Foo => "bar",
          Cheese => Bert->new( jeez => "louise" )
        );

This is a lot different to most serialisation systems in that it actually calls the constructor nicely. You can get it to call a different constructor by sub-classing Doc::Perlish::Data::Thaw.

note: To get the above behaviour, you'd actually need to either turn on the unsafe mode mode of Doc::Perlish::Data::Thaw, or pass in a classmap mapping element names to constructors;

my $warmer_for_above_example = Doc::Perlish::Data::Thaw->new
    ( classmap => { Bob => "Bob", Bert => "Bert" },
    );

Alternatively, you can tie the Doc::Perlish::Data::Thaw object to a Doc::Perlish::Scottish object (still in design stages) that is capable of performing appropriate decisions via various hooks in Doc::Perlish::Data::Thaw that will no doubt receive testing sooner or later.

BUGS AND LIMITATIONS

See www.yaml.org for a way for sending data structures around that conforms to standards and doesn't suck kumara.

SEE ALSO

Doc::Perlish::Data::Chill, Perldoc::Writer::XML, Doc::Perlish::Data::Thaw, Perldoc::Parser::XML.