PYX-XMLSchema-List
view release on metacpan or search on metacpan
package PYX::XMLSchema::List;
use strict;
use warnings;
use Class::Utils qw(set_params);
use Error::Pure qw(err);
use List::Util qw(reduce);
use PYX::Parser;
use Readonly;
# Constants.
Readonly::Scalar our $EMPTY_STR => q{};
Readonly::Scalar our $SPACE => q{ };
our $VERSION = 0.06;
# Constructor.
sub new {
my ($class, @params) = @_;
my $self = bless {}, $class;
# Output handler.
$self->{'output_handler'} = \*STDOUT;
# Process params.
set_params($self, @params);
# PYX::Parser object.
$self->{'_pyx_parser'} = PYX::Parser->new(
'callbacks' => {
'attribute' => \&_call_attribute,
'final' => \&_call_final,
'start_element' => \&_call_start_element,
},
'non_parser_options' => {
'schemas' => {},
},
'output_handler' => $self->{'output_handler'},
);
# Object.
return $self;
}
# Parse pyx text or array of pyx text.
sub parse {
my ($self, $pyx, $out) = @_;
$self->{'_pyx_parser'}->parse($pyx, $out);
return;
}
# Parse file with pyx text.
sub parse_file {
my ($self, $file, $out) = @_;
$self->{'_pyx_parser'}->parse_file($file, $out);
return;
}
# Parse from handler.
sub parse_handler {
my ($self, $input_file_handler, $out) = @_;
$self->{'_pyx_parser'}->parse_handler($input_file_handler, $out);
return;
}
# Reset parser.
sub reset {
my $self = shift;
$self->{'_pyx_parser'}->{'non_parser_options'}->{'schemas'} = {};
return;
}
# Gets statistics structure.
sub stats {
my $self = shift;
my $schemas_hr = $self->{'_pyx_parser'}->{'non_parser_options'}
->{'schemas'};
return $schemas_hr;
}
# Attribute callback.
sub _call_attribute {
my ($pyx_parser_obj, $key, $val) = @_;
my $schemas_hr = $pyx_parser_obj->{'non_parser_options'}->{'schemas'};
if (my ($first, $sec) = _parse_schema($key)) {
# Get URL for XML schema.
if ($first eq 'xmlns') {
my $schema = $sec;
if (! exists $schemas_hr->{$schema}) {
_init_struct($schemas_hr, $schema, $val);
} else {
$schemas_hr->{$schema}->[0] = $val;
}
# Add attribute to XML schema statistics.
} else {
my $schema = $first;
_init_struct($schemas_hr, $schema);
$schemas_hr->{$schema}->[1]->{'attr'}++;
}
}
return;
}
# Finalize callback.
sub _call_final {
my $pyx_parser_obj = shift;
my $schemas_hr = $pyx_parser_obj->{'non_parser_options'}->{'schemas'};
my $out = $pyx_parser_obj->{'output_handler'};
my $max_string = reduce { length($a) > length($b) ? $a : $b } keys %{$schemas_hr};
my $max_len = defined $max_string ? length $max_string : 0;
foreach my $key (sort keys %{$schemas_hr}) {
printf {$out} "[ %-${max_len}s ] (E: %04d, A: %04d)%s\n", $key,
$schemas_hr->{$key}->[1]->{'element'},
$schemas_hr->{$key}->[1]->{'attr'},
$schemas_hr->{$key}->[0] ne $EMPTY_STR
? $SPACE.$schemas_hr->{$key}->[0]
: $EMPTY_STR;
}
if (! keys %{$schemas_hr}) {
print {$out} "No XML schemas.\n";
}
return;
}
# Start of element callback.
sub _call_start_element {
my ($pyx_parser_obj, $elem) = @_;
my $schemas_hr = $pyx_parser_obj->{'non_parser_options'}->{'schemas'};
if (defined(my $schema = _parse_schema($elem))) {
_init_struct($schemas_hr, $schema);
$schemas_hr->{$schema}->[1]->{'element'}++;
}
return;
}
# Initialize XML schema structure.
sub _init_struct {
my ($schemas_hr, $schema, $uri) = @_;
if (! defined $uri) {
$uri = $EMPTY_STR;
}
if (! exists $schemas_hr->{$schema}) {
$schemas_hr->{$schema} = [$uri, {
'attr' => 0,
'element' => 0,
}];
}
return;
}
# Parse XML schema from string.
sub _parse_schema {
my $string = shift;
if ($string =~ m/^(.+?):(.+)$/ms) {
return wantarray ? ($1, $2) : $1;
}
return;
}
1;
__END__
=pod
=encoding utf8
=head1 NAME
PYX::XMLSchema::List - Processing PYX data or file and print list of XML schemas.
=head1 SYNOPSIS
use PYX::XMLSchema::List;
my $obj = PYX::XMLSchema::List->new(%parameters);
$obj->parse($pyx, $out);
$obj->parse_file($input_file, $out);
$obj->parse_handler($input_file_handler, $out);
$obj->reset;
my $stats_hr = $obj->stats;
=head1 METHODS
=head2 C<new>
my $obj = PYX::XMLSchema::List->new(%parameters);
Constructor.
=over 8
=item * C<output_handler>
Output handler.
Default value is \*STDOUT.
=back
Returns instance of object.
=head2 C<parse>
$obj->parse($pyx, $out);
Parse PYX text or array of PYX text and print list of XML schemas of PYX input.
If C<$out> not present, use 'output_handler'.
Returns undef.
=head2 C<parse_file>
$obj->parse_file($input_file, $out);
Parse file with PYX data and print list of XML schemas of PYX input.
If C<$out> not present, use 'output_handler'.
Returns undef.
=head2 C<parse_handler>
$obj->parse_handler($input_file_handler, $out);
Parse PYX handler and print list of XML schemas of PYX input.
If C<$out> not present, use 'output_handler'.
Returns undef.
=head2 C<reset>
$obj->reset;
Resets internal structure with statistics.
Returns undef.
=head2 C<stats>
my $stats_hr = $obj->stats;
Gets statistics structure.
Returns undef.
=head1 ERRORS
new():
From Class::Utils::set_params():
Unknown parameter '%s'.
=head1 EXAMPLE1
=for comment filename=list_xml_schemas.pl
use strict;
use warnings;
use PYX::XMLSchema::List;
# Example data.
my $pyx = <<'END';
(foo
Axmlns:bar http://bar.foo
Axmlns:foo http://foo.bar
Afoo:bar baz
(foo:bar
Axml:lang en
Abar:foo baz
)foo:bar
)foo
END
# PYX::XMLSchema::List object.
my $obj = PYX::XMLSchema::List->new;
# Parse.
$obj->parse($pyx);
# Output:
# [ bar ] (E: 0000, A: 0001) http://bar.foo
# [ foo ] (E: 0001, A: 0001) http://foo.bar
# [ xml ] (E: 0000, A: 0001)
=head1 DEPENDENCIES
L<Class::Utils>,
L<Error::Pure>,
L<List::Util>,
L<PYX::Parser>,
L<Readonly>.
=head1 SEE ALSO
=over
=item L<PYX>
A perl module for PYX handling.
=item L<Task::PYX>
Install the PYX modules.
=back
=head1 REPOSITORY
L<https://github.com/michal-josef-spacek/PYX-XMLSchema-List>
=head1 AUTHOR
Michal Josef Å paÄek L<mailto:skim@cpan.org>
L<http://skim.cz>
=head1 LICENSE AND COPYRIGHT
© 2015-2023 Michal Josef Å paÄek
BSD 2-Clause License
=head1 VERSION
0.06
=cut
( run in 0.353 second using v1.01-cache-2.11-cpan-7add2cbd662 )