XML-API
view release on metacpan or search on metacpan
lib/XML/API.pm view on Meta::CPAN
my $element = shift || croak '_open($element,...)';
my $namespace = $self->{namespace};
# reset the output string in case it has been cached
$self->{string} = undef;
if ( $element eq $self->_root_element ) {
$self->{has_root_element} = 1;
}
my $attrs = {};
my @content;
my $total = scalar(@_) - 1;
my $next;
foreach my $i ( 0 .. $total ) {
if ($next) {
$next = undef;
next;
}
my $arg = $_[$i];
if ( ref($arg) eq 'HASH' ) {
while ( my ( $key, $val ) = each %$arg ) {
$attrs->{$key} = _escapeXML($val);
if ( !defined($val) ) {
carp "attribute '$key' undefined (element '$element')";
$attrs->{$key} = '';
}
}
}
elsif ( defined($arg) and $arg =~ m/^-[^0-9\.]+/o ) {
$arg =~ s/^-//o;
$attrs->{$arg} = _escapeXML( $_[ ++$i ] );
if ( !defined( $attrs->{$arg} ) ) {
carp "attribute '$arg' undefined (element '$element') ";
$attrs->{$arg} = '';
}
$next = 1;
next;
}
else {
push( @content, $arg );
}
}
#
# Start with the default root element attributes and add those
# given if this is the root element
#
if ( $element eq $self->_root_element ) {
my $rootattrs = $self->_root_attrs;
while ( my ( $key, $val ) = each %$attrs ) {
$rootattrs->{$key} = $val;
}
$attrs = $rootattrs;
}
my ( $file, $line ) = (caller)[ 1, 2 ] if ( $self->{debug} );
if ( $self->{langnext} ) {
$attrs->{'xml:lang'} = delete $self->{langnext};
}
if ( $self->{dirnext} ) {
$attrs->{'dir'} = delete $self->{dirnext};
}
my $e;
if ( $self->{current} ) {
$e = XML::API::Element->new(
element => $element,
attrs => $attrs,
ns => $namespace,
parent => $self->{current},
);
$self->_add($e);
}
else {
$e = XML::API::Element->new(
element => $element,
attrs => $attrs,
ns => $namespace,
);
push( @{ $self->{elements} }, $e );
}
$self->{current} = $e;
if ( $self->{_raw} ) {
$self->_raw(@content);
}
else {
$self->_add(@content);
}
$self->_comment("DEBUG: '$element' (open) at $file:$line")
if ( $self->{debug} );
return $e;
}
sub _add {
my $self = shift;
$self->{string} = undef;
if ( !$self->{current} ) {
croak 'Cannot use _add with no current element';
}
foreach my $item (@_) {
carp "undefined input" unless ( defined($item) );
if ( eval { $item->isa(__PACKAGE__) } ) {
if ( refaddr($item) == refaddr($self) ) {
croak 'Cannot _add object to itself';
}
if ( !$self->{current} ) {
push( @{ $self->{elements} }, $item );
}
else {
$self->{current}->add($item);
}
bless( $item, ref($self) );
$item->{parent} = $self;
weaken( $item->{parent} );
foreach my $lang ( keys %{ $item->{langs} } ) {
$self->{langs}->{$lang} = 1;
}
}
else {
if ( eval { $item->isa('XML::API::Element') } ) {
$self->{current}->add($item);
}
elsif ( eval { $item->isa('XML::API::Cache') } ) {
foreach my $lang ( $item->langs ) {
$self->{langs}->{$lang} = 1;
}
$self->{current}->add($item);
}
else {
$self->{current}->add( _escapeXML($item) );
}
}
}
}
sub _raw {
my $self = shift;
$self->{string} = undef;
foreach my $item (@_) {
carp "undefined input" unless ( defined($item) );
if ( ref($item) and $item->isa(__PACKAGE__) ) {
croak 'Cannot add XML::API objects as raw';
}
if ( $self->{current} ) {
$self->{current}->add($item);
}
else {
push( @{ $self->{elements} }, $item );
}
}
}
sub _close {
my $self = shift;
my $element = shift || croak '_close($element)';
my ( $file, $line ) = (caller)[ 1, 2 ] if ( $self->{debug} );
if ( !$self->{current} ) {
carp 'attempt to close non-existent element "' . $element . '"';
return;
}
if ( $element eq $self->{current}->{element} ) {
if ( $self->{current}->parent ) {
$self->{current} = $self->{current}->parent;
$self->_comment("DEBUG: '$element' close at $file:$line")
if ( $self->{debug} );
}
else {
$self->{current} = undef;
}
}
else {
carp 'attempted to close element "'
. $element
. '" when current '
. 'element is "'
. $self->{current}->{element} . '"';
}
return;
}
sub _element {
my $self = shift;
my $element = shift || croak '_element($element)';
my $e = $self->_open( $element, @_ );
$self->_close($element);
return $e;
}
#
# The implementation for element, element_open and element_close
#
sub AUTOLOAD {
my $self = shift;
my $element = $AUTOLOAD;
my ( $open, $close ) = ( 0, 0 );
if ( $element =~ s/.*::(.+)_open$/$1/o ) {
my $old_ns = $self->{namespace};
if ( $element =~ s/(.+)__(.+)/$2/o ) {
$self->{namespace} = $1;
}
my $e = $self->_open( $element, @_ );
$self->{namespace} = $old_ns;
return $e;
}
elsif ( $element =~ s/.*::(.+)_close$/$1/o ) {
$element =~ s/(.+)__(.+)/$2/o;
return $self->_close($element);
}
elsif ( $element =~ s/.*::(.+)_raw$/$1/o ) {
( run in 0.359 second using v1.01-cache-2.11-cpan-524268b4103 )