package My::XML::Generator; use strict; use warnings; use Exporter qw( import ); use XML::LibXML qw( ); our @EXPORT_OK = qw( gen_document gen_root_element gen_element gen_data_element ); our %EXPORT_TAGS = ( 'all' => \@EXPORT_OK ); # -------------------- # Public Functions sub gen_document { my $doc = XML::LibXML::Document->new('1.0', 'UTF-8'); $doc->setDocumentElement(gen_root_element(@_)); return $doc->toString(); } # Can't use objects passed as children after calling this. sub gen_root_element { my $name = shift; my $children = pop; my $root = XML::LibXML::Element->new($name); while (@_) { my $key = shift; my $val = shift; if ($key eq '__NAMESPACE') { $root->setNamespace($val); } else { $root->setAttribute($key, $val); } } foreach (@$children) { $root->addChild($_); } return $root; } # Can't use objects passed as children after calling this. sub gen_element { my $name = shift; my $children = @_ % 2 == 1 ? pop : []; my $ele = XML::LibXML::Element->new($name); while (@_) { $ele->setAttribute(shift, shift); } foreach (@$children) { $ele->addChild($_); } return $ele; } sub gen_data_element { my $name = shift; my $text = shift; my $ele = XML::LibXML::Element->new($name); while (@_) { $ele->setAttribute(shift, shift); } $ele->appendTextNode($text); return $ele; } 1; __END__ =head1 NAME My::XML::Generator - A fast XML generator. =head1 SYNOPSIS use My::XML::Generator qw( gen_document gen_element gen_data_element ); sub gen_breakdown { ... return gen_element('PTC_Farebreakdown', [ gen_element('PassengerTypeQuantity', 'Code' => format_pax_type($pax_type), 'Quantity' => $pax_qty, ), gen_element('PassengerFare', [ gen_element('BaseFare', 'Amount' => $base_fare), gen_element('Taxes', [ gen_data_element('Tax', 'Taxes and Surcharges', 'Amount' => $tax_and_surch), ]), gen_element('TotalFare', 'Amount' => $total), ]), ]); }