Builder
view release on metacpan or search on metacpan
lib/Builder/XML.pm view on Meta::CPAN
}
sub AUTOLOAD {
my ( $self ) = shift;
my @args = @_;
if ( $AUTOLOAD =~ /.*::(.*)/ ) {
my $elt = $1;
my $attr = undef;
# sub args get resent as callback
if ( wantarray ) {
return sub { $self->$elt( @args ) };
}
# if first arg is hasharray then its attributes!
$attr = shift @args if ref $args[0] eq 'HASH';
if ( ref $args[0] eq 'CODE' ) {
$self->__element__( context => 'start', element => $elt, attr => $attr );
for my $inner ( @args ) {
if ( ref $inner eq 'CODE' ) { $inner->() }
else { $self->__push__( sub { $inner } ) }
}
$self->__element__( context => 'end', element => $elt );
return;
}
# bog standard element
$self->__element__( element => $elt, attr => $attr, text => "@args" );
}
$self;
}
######################################################
# methods
sub __render__ {
my $self = shift;
my $render;
# render subs just for this block
my @this_block = Builder::Utils::yank { $_->[0] == $self->{block_id} } @{ $self->{stack} };
while ( my $block = shift @this_block ) {
my ( $block_id, $code ) = @$block;
$render.= $code->();
}
return $render;
}
sub __element__ {
my ( $self, %param ) = @_;
$param{ text } ||= '';
$param{ context } ||= 'element';
$self->{ context }->{ $param{ context } }->( $self, \%param );
return;
}
sub __cdata__ {
my $self = shift;
return $_[0] if $self->{ cdata } == 1;
return $self->__cdatax__( $_[0] );
}
sub __cdatax__ {
my $self = shift;
return q{<![CDATA[} . $_[0] . q{]]>};
}
sub __say__ {
my ( $self, @say ) = @_;
for my $said ( @say ) { $self->__push__( sub { $said } ) }
$self;
}
sub __push__ {
my ( $self, $code ) = @_;
# straight to output stream if provided
if ( $self->{ _output } ) {
print { $self->{ _output } } $code->();
return;
}
# else add to stack
push @{ $self->{ stack } }, [ $self->{ block_id }, $code ];
}
sub __inc__ { $_[0]->{ _inc }->() }
sub __dec__ { $_[0]->{ _dec }->() }
sub __level__ { $_[0]->{ _level }->() }
sub __tab__ {
my $self = shift;
my $tab = q{};
$tab = q{ } x $self->{ pre_indent } if $self->{ pre_indent };
$tab.= q{ } x ( $self->{ indent } * $self->__level__ ) if $self->{ indent };
return $tab;
}
sub __start_tab__ { $_[0]->__tab__ }
sub __end_tab__ {
my $self = shift;
return q{} if $self->{ newline } && ! $self->{ open_newline };
$self->__tab__;
}
sub __open_newline__ {
my $self = shift;
return $self->{cr} if $self->{ open_newline };
return q{};
}
sub __close_newline__ {
my $self = shift;
return $self->{cr} if $self->{ close_newline };
return q{};
}
sub DESTROY {
my $self = shift;
$self = undef;
lib/Builder/XML.pm view on Meta::CPAN
$xm->div(
$xm->div(
xm->span( 'hi there'),
),
);
# => <div><div><span>hi there</span></div></div>
=head2 Gotchas?
TODO: XML entities not implemented
TODO: invalid method calls... $xm->flip-flop, $xm->DESTROY, $xm->AUTOLOAD
TODO: Fix / workaround for attribute ordering
=head1 EXPORT
None.
=head1 METHODS
All methods are prefix/postfixed with __ so that ambigious method calls wont clash
and can be turned successfully into XML elements.
Below is a complete list of defined methods in Builder::XML.
NB. Most of these are private methods and only listing here for reference.
=head2 __new__
Private.
This is the contructor called by the Builder object when creating a block...
$xm = $builder->block( 'Builder::XML' );
All arguments are passed from Builder->block method straight to Builder::XML->__new__
=head2 __render__
Will immediately render the building block.
Can be useful in some cases...
# provide example here of it working
# and then provide example of what can go wrong!
...but recommend $builder->render for best practise.
=head2 __element__
Private
=head2 __cdata__
Wraps content in <![CDATA[ ]]> element.
Useful for quick ditties like....
$xm->span( $xm->__cdata__( 'yada yada' ) );
# => <span><!CDATA[yada yada]]></span>
But for best practise you probably still find building a block more useful in the long run...
my $xm = $builder->block( 'Builder::XML', { cdata => 1 } );
$xm->span( 'yada yada' );
=head2 __cdatax__
PRIVATE - used with __cdata__
=head2 __say__
Really a Private method but as mentioned in I<Gotchas> it can be useful for working around some implementation issues.
=head2 __push__
Private
=head2 __inc__
Private
=head2 __dec__
Private
=head2 __level__
Private
=head2 __tab__
Private
=head2 __start_tab__
Private
=head2 __end_tab__
Private
=head2 __open_newline__
Private
=head2 __close_newline__
Private
=head2 AUTOLOAD
Used in method to XML element resolution.
Therefore at present AUTOLOAD cannot be used as a XML element.
=head2 DESTROY
( run in 0.543 second using v1.01-cache-2.11-cpan-6aa56a78535 )