#!/usr/bin/env perl use strict; use warnings; use utf8; use XML::Parser; use Data::Dumper; # Reads the servlets partial XML file using XML::Parser, # Then converts the obtained data structure to a more readable one # Example conversion: =xml library The standard gsdl3 library program org.greenstone.gsdl3.LibraryServlet library_name library site_name localsite =cut =data_structure { 'servlet' => { 'servlet-class' => 'org.greenstone.gsdl3.LibraryServlet', 'servlet-name' => 'library', 'description' => { '.value' => 'The standard gsdl3 library program', '.attr' => { 'attribute' => 'example' } }, 'init-param' => [ { 'param-value' => 'library', 'param-name' => 'library_name' }, { 'param-name' => 'site_name', 'param-value' => 'localsite' } ] } } =cut sub read_servlets { my $file = shift; # The xml needs a root element, so we wrap it in one my $xml=' ] > <__root__> &real_doc; '; # Parse the data using XML::Parser my $data = new XML::Parser (Style => 'Tree')->parse ($xml); sub tidy { my %hash; # If the element has attributes, add them to the hash my $attr = shift; if (scalar keys %$attr > 0) { $hash{'.attr'} = $attr; } # Read any child elements or text value while (@_) { my $element = shift; my $value = shift; if ($element eq 0) { $value =~ /^\s*$/ || ($hash{'.value'} .= $value); } else { # If there is more than one of a single tupe of child element, # That child element must become an array if (defined $hash{$element}) { unless (ref $hash{$element} eq 'ARRAY') { $hash{$element} = [ $hash{$element} ]; } push @{$hash{$element}}, tidy (@{$value}); } else { $hash{$element} = tidy (@{$value}); } } } # If the element only has a value, it can become a scalar if (scalar keys %hash == 1 and defined $hash{'.value'}) { return $hash{'.value'}; } return \%hash; } return tidy (@{@$data[1]}); } # Writes a data structure to an XML file sub write_servlets { my ($hash, $file) = @_; open OUT, '>', $file; sub open_tag { my ($indent, $tag, $attr) = @_; print OUT $indent, "<", $tag; if (defined $attr) { for my $key (sort keys %$attr) { print OUT " ", $key, '="', $attr->{$key}, '"'; } } print OUT ">"; } sub write_xml { my ($indent, $hash) = @_; for my $key (sort keys %$hash) { $key eq '.attr' && next; my $val = $hash->{$key}; $key eq '.value' && do { print OUT $val, "\n"; next; }; for (ref $val) { /^ARRAY$/ && do { for my $element (@$val) { open_tag ($indent, $key, $element->{'.attr'}); for (ref $element) { /^HASH$/ && do { print OUT "\n"; write_xml (" $indent", $element); print OUT $indent, "\n"; last; }; print OUT $element, "\n"; } } last; }; /^HASH$/ && do { open_tag ($indent, $key, $val->{'.attr'}); # If the element only has a value with attributes, # it can be formatted on one line if (scalar keys %$val == 2 and defined $val->{'.value'}) { print OUT $val->{'.value'}, "\n"; } else { print OUT "\n"; write_xml (" $indent", $val); print OUT $indent, "\n"; } last; }; open_tag ($indent, $key); print OUT $val; print OUT "\n"; } } } write_xml ("", $hash); close OUT; } my $hash; # Hackish non-interactive CLI parser while (@ARGV) { for (shift) { /^read$/i && do { $hash = read_servlets (shift); last; }; /^write$/i && do { write_servlets ($hash, shift); last; }; /^debug$/i && do { print Dumper $hash; last; }; /^count$/i && do { print "Found ", scalar @{$hash->{servlet}}, " servlets\n"; last; }; /^list$/i && do { print "Servlets:\n"; for my $servlet (@{$hash->{servlet}}) { print " ", $servlet->{'servlet-name'}, "\n"; } last; }; } }