The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package PICA::XMLWriter;

=head1 NAME

PICA::XMLWriter - Write and count PICA+ records and fields in XML format

=cut

use strict;
use utf8;

use base qw( PICA::Writer );
our $VERSION = "0.44";

#use PICA::Writer;
use Carp qw(croak);

our $NAMESPACE = 'info:srw/schema/5/picaXML-v1.0';

=head1 METHODS

=head2 new ( [ <file-or-handle> ] [, %parameters ] )

Create a new XML writer.

=cut

sub new {
    my $class = shift;
    my ($fh, %params) = @_ % 2 ? @_ : (undef, @_);
    my $self = bless { 
        header => $params{header},
        xslt => $params{xslt},
        collection => defined $params{collection} ? $params{collection} : 1,
    }, $class;
    return $self->reset($fh);
}

=head2 write ( [ $comment, ] $record [, $record ... ] )

Write a record(s) of type L<PICA::Record>. You can also pass
strings that will be printed as comments. Please make sure to
have set the default namespace ('info:srw/schema/5/picaXML-v1.0')
to get valid PICA XML.

This method does not write an XML header and footer but you can
easily chain method calls like this:

  $writer->start_document()->write($record)->end_document();

=cut

sub write {
    my $self = shift;

    my $comment = "";
    while (@_) {
        my $record = shift;

        if (ref($record) eq 'PICA::Record') {
            if ( $self->{filehandle} ) {
                print { $self->{filehandle} } $record->to_xml() ;
            }
            $comment = "";

            $self->{recordcounter}++;
            $self->{fieldcounter} += scalar $record->all_fields;
        } elsif (ref(\$record) eq 'SCALAR') {
            next if !$record;
            $comment .= "\n" if $comment;
            $comment .= '# ' . join("\n# ", split(/\n/,$record)) . "\n";
            $comment =~ s/--//g;
            print "<!-- $comment -->";
        } else {
            croak("Cannot write object of unknown type (PICA::Record expected)!");
        }
    }
    $self;
}

=head2 writefield ( $field [, $field ... ] )

Write one ore more C<PICA::Field> in XML, based on C<PICA::Field->to_xml>.

=cut

sub writefield {
    my $self = shift;
    while (@_) {
        my $field = shift;
        if (ref($field) ne 'PICA::Field') {
            croak("Cannot write object of unknown type (PICA::Field expected)!");
        } else {
            print { $self->{filehandle} } $field->to_xml() if $self->{filehandle};
            $self->{fieldcounter}++;
        }
    }
}

=head2 start_document ( [ %params ] )

Write XML header and collection start element. 
The default namespace is set to 'info:srw/schema/5/picaXML-v1.0'.

Possible parameters include 'stylesheet' to add an XSLT script reference.

=cut

sub start_document {
    my $self = shift;
    my %params = @_;

    # TODO: see PICA::Record->to_xml and combine
    my @xml;

    if ($params{header}) {
        push @xml, "<?xml version='1.0' encoding='UTF-8'?>";
        $params{collection} = 1;
    }

    if ($self->{filehandle}) {
        push @xml, "<?xml version='1.0' encoding='UTF-8'?>";
        if ($params{xslt}) {
            my $xslt = $params{xslt};
            $xslt =~ s/'/&apos/;
            push @xml, "<?xml-stylesheet type='text/xsl' href='$xslt'?>";
        }
        push @xml, "<collection xmlns='" . $NAMESPACE . "'>";
    }
    print { $self->{filehandle} } join("\n",@xml)."\n" if @xml;
    $self->{in_doc} = 1;
    $self;
}

=head2 end_document ( )

Write XML footer (collection end element).
Note that this method does close the file handle if you write to a file.

=cut

sub end_document {
    my $self = shift;
    print { $self->{filehandle} } "</collection>\n" if $self->{filehandle} and $self->{in_doc};
    $self->{in_doc} = 0;
}

1;

__END__

=head1 AUTHOR

Jakob Voss C<< <jakob.voss@gbv.de> >>

=head1 LICENSE

Copyright (C) 2007-2009 by Verbundzentrale Göttingen (VZG) and Jakob Voß

This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself, either Perl version 5.8.8 or, at
your option, any later version of Perl 5 you may have available.