The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.


XML::Spew - Spew small chunks of XML


Version 0.01


    package My::Spew;

    use base 'XML::Spew';

    __PACKAGE__->_tags(qw/foo bar baz narf poit/);

    package main;

    my $spew = My::Spew->_new;

    print $spew->foo( $spew->bar( { id => 1 } ), 
                      $spew->bar( { id => 2 }, $spew->baz( "Hi-diddly-ho, neighborino." ) ) );


Sometimes you just need to quickly output a small chunk of XML and you don't need a big DOM API or XML framework. At the same time, you don't want to assemble tedious print statements or HERE-docs. You can subclass XML::Spew to create objects for easily generating well-formed XML element trees with a minimum of fuss. Spew does not guarantee document validity; you must take care to properly encode any special characters and ensure that your tags make sense.


XML::Spew is a base class. To make any use of it, you will need to write a subclass. An example class, XML::Spew::XHTML, is included in this distribution.

First, declare your package and make it a subclass of XML::Spew.

    package What::Ever;
    use base 'XML::Spew';

Your subclass will inherrit a number of class methods which will be used to auto-magically create the instance methods for your XML spewing needs. In order to avoid collisions with the names of XML tags, all the built-in XML::Spew methods begin with an underscore ('_').

To set up your tags, call the _tags method:

    __PACKAGE__->_tags( qw/foo bar baz narf poit/ );

That's it! You can now use your class to spew out chunks of XML.

    my $spew = What::Ever->_new;
    print $spew->start_foo;
    print $spew->bar( $spew->baz( { id => 1 }, "some text\n" ),
                      $spew->baz( { id => 2 }, "some other text\n" ) );
    print $spew->end_foo;

This produces the output:

    <foo><bar><baz id="1">some text
    </baz><baz id="2">some other text

Each tag that you configure with the _tags method actually gets three methods made, the "main" method, whose name is identical to the tag, the "start" method (start_$tag) and the "end" method (end_$tag). Spew keeps track of calls to start and end methods in an internal stack to ensure proper nesting of elements. The following generates a fatal error:

    print $spew->start_foo, $spew->start_bar, $spew->end_foo;

In this case, the <bar> tag was not closed before the <foo> tag.

A tag's main method always guarantees proper closure. If no child data is passed, it will generate a self-closing tag.

    print $spew->foo;              # prints '<foo />'

If child data is passed, it will generate a tag pair around it.

    print $spew->foo( "blah" );    # prints '<foo>blah</foo>'

If the first parameter to a main or start method is a hashref, the keys and values of the hashref will be used as attributes for the tag.

    print $spew->foo( { id => 1, a => "q" } );   # prints <foo id="1" a="q" />
    print $spew->foo( { id => 2 }, "blah" );     # prints <foo id="2">blah</foo>

Attribute hashrefs can also be passed to start methods.

If the child consists of an arrayref, the tag will be "distributed" over each element in the array. Any attributes will also be distributed.

    print $spew->foo( { quux => 42 }, [qw/red green blue/] );

    # prints:
    # <foo quux="42">red</foo><foo quux="42">green</foo><foo quux="42">blue</foo>

    print $spew->bar( [qw/tom dick harry/] );

    # prints:
    # <bar>tom</bar><bar>dick</bar><bar>harry</bar>

For tags to be distributed, the first child data item must be the arrayref. (Meaning either the first argument or the first argument after the attribute hashref.) Any child data after the arrayref will be ignored.


XML::Spew is designed to be quick and dirty. It is not a substitute for a full XML framework if you need to construct large, complex XML documents. Spew is for when you need to spew small chunks of XML quickly.

The functional nature of the main method interface and the internal tag stack will do its best to guarantee that your XML chunk is well-formed. Spew does not do any checking to ensure that a given tag is allowed inside another, nor does it inspect child data for things that need encoding or escaping.


Thanks to Lincoln Stein for inspiring the interface with his ubiquitous CGI module.


Mike Friedman, <>


Please report any bugs or feature requests to, or through the web interface at I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.


Copyright 2005 Mike Friedman, all rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.