NAME
XML::Writer::Nest - dataElement() for when you need to embed elements, not data
SYNOPSIS
use
XML::Writer::Nest;
my
$writer
= new XML::Writer;
{
my
$level1
= XML::Writer::Nest->new(
tag
=>
'level1'
,
attr
=> [
hee
=>
'haw'
,
fee
=>
'fi'
],
writer
=>
$writer
);
{
my
$level2
=
$level1
->nest(
level2
=> [
attr1
=> 3 ] );
# or call the class conc. again.
{
my
$level3
=
$level2
->nest(
'level3'
);
}
# endTag created automatically
}
# endTag created automatically
}
# endTag created automatically
Vanilla XML::Writer would not have indentation and you would have to manually close your start tags:
$writer
->startTag(
"level1"
);
$writer
->startTag(
"level2"
);
$writer
->startTag(
"level3"
);
$writer
->endTag();
$writer
->endTag();
$writer
->endTag();
DESCRIPTION
When nesting XML elements with XML::Writer, you have to manually close your startTags. Also, you dont necessarily have any visual feedback via indentation for each level of tag nesting.
XML::Writer::Nest
solves both of those problems.
XML::Generator
XML::Generator solves this problem a different way. But I dont see an easy way to make use of object-oriented dispatch to specialize and generalize XML production with it.
My current module and Moose's inner
work just fine together.
API
There is a class-level constructor and an object-level constructor. The class level constructor requires 3 arguments (tag, attributes, and XML::Writer
instance). The object-level constructor only requires tag and attribute arguments - it passes along the XML::Writer
instance.
NOTE: This module operates based on lexical scope. So both object and class level construction are done right after creating a new lexical scope with braces.
Class-based constructor
{
my
$xml_nest
= XML::Writer::Nest->new(
tag
=>
'tagname'
,
attr
=> \
@attr
,
writer
=>
$xml_writer
);
# add some additional things for this nest level via $xml_writer->api_calls
}
# when $xml_nest goes out of scope, it calls $xml_writer->endTag automatically
Object-based constructor
{
my
$xml_nest2
=
$xml_nest
->nest(
tagname
=> \
@attr
);
# add some additional things for this nest level via $xml_writer->api_calls
}
# when $xml_nest2 goes out of scope, it calls $xml_writer->endTag automatically
{
my
$xml_nest2
=
$xml_nest
->nest(
tagname
=>
@attr
);
# add some additional things for this nest level via $xml_writer->api_calls
}
# when $xml_nest2 goes out of scope, it calls $xml_writer->endTag automatically
Please note: the object-level constructor will either an arrayref or array of attributes. The class-based constructor will take only an arrayref of attributes.
DISCUSSION
Caveat emptor
If you wish to nest elements at the same level ("sibling elements"), then you must brace each:
#!/usr/bin/perl
use
strict;
use
XML::Writer::Nest;
my
$output
;
my
$writer
= new XML::Writer(
OUTPUT
=>
$output
);
my
$main
= new XML::Writer::Nest(
tag
=>
'main'
,
writer
=>
$writer
);
{
my
$head
=
$main
->nest(
'head'
);
}
{
my
$body
=
$main
->nest(
'body'
);
}
STDOUT
$output
.
"\n\n"
;
XML::Generator
XML::Generator is another module which allows for automatic creation of closing tags based on behavior of the Perl programming language.
From what I can see, one is not able to leverage object-oriented re-use of parts of the XML generation by delegating specialized aspects of the rendering to subclasses.
Concretely, Moose's augment function has demonstrated a way of allowing generic and specific aspects of XML generation to co-operate.
Therefore, I like Moose in combination with XML::Writer for object-oriented XML production. However, the automatic creation of closing XML tags by XML::Generator is quite attractive. Not only that, but the automatic source-code indentation is especially handy when you are creating highly nested XML.
Another thing I don't like about XML::Generator is that you must use one highly nested function call to produce the output document. I prefer brace-levels and a series of calls to the XML::Writer interface.
Practical Comparison
Let's take the synopsis example from XML::Generator and write it in all 3 approaches. First let's take a look at the desired XML output.
<bar baz=
"3"
>
<bam />
</bar>
<qux:bar>Hey there, world</qux:bar>
</foo>
XML::Generator
foo(bar({
baz
=> 3 }, bam()),
"Hey there, world"
));
AUTHOR
Terrence Brannon, <metaperl at gmail.com>
SEE ALSO
"Constructive Use of Destructors"
http://www.metaperl.org/publications
This talk to the Columbus, OH Perl mongers discusses XML::Writer::Nest in detail.
BUGS
Please report any bugs or feature requests to bug-xml-writer-nest at rt.cpan.org
, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=XML-Writer-Nest. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
SUPPORT
You can find documentation for this module with the perldoc command.
perldoc XML::Writer::Nest
You can also look for information at:
RT: CPAN's request tracker
AnnoCPAN: Annotated CPAN documentation
CPAN Ratings
Search CPAN
ACKNOWLEDGEMENTS
Many thanks to #moose, especially Jeese Luehrs (doy)!, matt trout, doy, and confound.
COPYRIGHT & LICENSE
Copyright 2009 Terrence Brannon, all rights reserved.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.