The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package XML::Tiny::Simple;
use Exporter 'import';
@EXPORT_OK = qw( parsefile parsestring );
use strict;
use warnings;

=head1 NAME

XML::Tiny::Simple - a tiny helper to read XML::Tiny output and transform it 
to something like XML::Simple, but without dependencies.

=head1 VERSION

Version 0.01

=cut

our $VERSION = '0.01';
use XML::Tiny;

=head1 SYNOPSIS


    use XML::Tiny::Simple qw(parsestring);

    my $doc = parsestring( *DATA );

    $doc->{root}->{branch}->{second}->{leaf}->[0]->{flower};  # "false"
    $doc->{root}->{branch}->{second}->{leaf}->[0]->{content}; #"a dead leaf"
    $doc->{root}->{branch}->{first}->{name}; "first"
    $doc->{root}->{branch}->{first}->{tag}; "branch"
__DATA__
    <?xml version="1.0" encoding="utf-8" ?>
    <root>
     <branch name="first"/>
     <branch name="second">
      <leaf flower="false">a dead leaf</leaf>
      <leaf flower="true">another leaf</leaf>
     </branch>
    </root>

=head1 SUBROUTINES/METHODS

=head2 parsefile

Read xml document from the given file name. 
For options, see XML::Tiny's parsefile documentation.

=cut

sub parsefile{
	my $doc = XML::Tiny::parsefile( @_ );
	my $new = traverse( $doc->[0] );
	return $new;
}

=head2 parsestring

Same as parsefile but take a string or an opened filehandle with the XML content

=cut

sub parsestring{
	if(fileno $_[0]){
		my $FH = shift;
		unshift @_, join '', <$FH>;
	}
	
	$_[0] = '_TINY_XML_STRING_' . $_[0];
	&parsefile;
}

=head2 traverse 

Take a document or sub-element in the XML::Tiny format, and an optional parent node.
It will return the document in the XML::Tiny::Simple format.

=cut

sub traverse{
	my ($obj, $node) = @_;
	$node = { } unless $node;
	
	if(ref $obj eq 'HASH'){
		if($obj->{type} eq 'e'){
			#prepare a tag element
			my $class = $obj->{name};
			#add attributs
			my %att = exists $obj->{attrib} ? %{$obj->{attrib}} : ( );
			my $elt = { tag => $class, %att };
			#add childs
			foreach my $childobj( @{$obj->{content}} ){
				my $childelt = traverse( $childobj, $elt );
			}
			#add element in parent $node
			my $name = $obj->{attrib}->{name};
			if($name){
				if(exists($node->{ $class }->{ $name })){
					my $first = $node->{ $class }->{ $name };
					if(ref $first eq 'ARRAY'){
						push @$first, $elt;
					}
					else{
						$node->{ $class }->{ $name } = [ $first, $elt ];
					}
				}
				else{
					$node->{ $class }->{ $name } = $elt;
				}
			}
			else{
				if(exists($node->{ $class })){
					my $first = $node->{ $class };
					if(ref $first eq 'ARRAY'){
						push @$first, $elt;
					}
					else{
						$node->{ $class } = [ $first, $elt ];
					}
				}
				else{
					$node->{ $class } = $elt;
				}				
			}
		}
		elsif($obj->{type} eq 't'){
			#add element content
			$node->{content} = $obj->{content};
		}
	}
	elsif(ref $obj eq 'ARRAY'){
		die("traverse(ARRAY ref) is uncovered, please inform the author\n", 
					join ',', @{$obj} );
	}
	else{
		$node->{'content'} = $obj;
	}
	
	return $node;
}

=head1 AUTHOR

Nicolas Georges, C<< <xlat at cpan.org> >>

=head1 BUGS

Please report any bugs or feature requests to C<bug-xml-tiny-simple at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=XML-Tiny-Simple>.  I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.




=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc XML::Tiny::Simple


You can also look for information at:

=over 4

=item * RT: CPAN's request tracker (report bugs here)

L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=XML-Tiny-Simple>

=item * AnnoCPAN: Annotated CPAN documentation

L<http://annocpan.org/dist/XML-Tiny-Simple>

=item * CPAN Ratings

L<http://cpanratings.perl.org/d/XML-Tiny-Simple>

=item * Search CPAN

L<http://search.cpan.org/dist/XML-Tiny-Simple/>

=back


=head1 ACKNOWLEDGEMENTS


=head1 LICENSE AND COPYRIGHT

Copyright 2012 Nicolas Georges.

This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.


=cut

1; # End of XML::Tiny::Simple