|
From: Grant M. <gr...@us...> - 2002-10-17 07:29:50
|
Update of /cvsroot/perl-xml/xml-simple/lib/XML
In directory usw-pr-cvs1:/tmp/cvs-serv26769/lib/XML
Modified Files:
Simple.pm
Log Message:
- added 'strict mode' and bumped version to 2.00
Index: Simple.pm
===================================================================
RCS file: /cvsroot/perl-xml/xml-simple/lib/XML/Simple.pm,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- Simple.pm 13 Oct 2002 01:16:31 -0000 1.1
+++ Simple.pm 17 Oct 2002 07:29:45 -0000 1.2
@@ -24,6 +24,10 @@
my $xml = $xs->XMLout($hashref [, <options>]);
+Or to catch common errors:
+
+ use XML::Simple qw(:strict);
+
(or see L<"SAX SUPPORT"> for 'the SAX way').
=cut
@@ -46,9 +50,10 @@
@ISA = qw(Exporter);
@EXPORT = qw(XMLin XMLout);
-$VERSION = '1.08_01';
+$VERSION = '2.00';
$PREFERRED_PARSER = undef;
+my $StrictMode = 0;
my %CacheScheme = (
storable => [ \&StorableSave, \&StorableRestore ],
memshare => [ \&MemShareSave, \&MemShareRestore ],
@@ -79,6 +84,22 @@
##############################################################################
+# Wrapper for Exporter - handles ':strict'
+#
+
+sub import {
+
+ # Handle the :strict tag
+
+ $StrictMode = 1 if grep(/^:strict$/, @_);
+
+ # Pass everything else to Exporter.pm
+
+ __PACKAGE__->export_to_level(1, grep(!/^:strict$/, @_));
+}
+
+
+##############################################################################
# Constructor for optional object interface.
#
@@ -625,6 +646,32 @@
$opt->{parseropts} = [ ];
}
+
+ # Special cleanup for {forcearray} which could be arrayref or boolean
+ # or left to default to 0
+
+ if(exists($opt->{forcearray})) {
+ if(ref($opt->{forcearray}) eq 'ARRAY') {
+ if(@{$opt->{forcearray}}) {
+ $opt->{forcearray} = { (
+ map { $_ => 1 } @{$opt->{forcearray}}
+ ) };
+ }
+ else {
+ $opt->{forcearray} = 0;
+ }
+ }
+ else {
+ $opt->{forcearray} = ( $opt->{forcearray} ? 1 : 0 );
+ }
+ }
+ else {
+ if($StrictMode) {
+ croak "No value specified for 'forcearray' option in call to XML$dirn()";
+ }
+ $opt->{forcearray} = 0;
+ }
+
# Special cleanup for {keyattr} which could be arrayref or hashref or left
# to default to arrayref
@@ -641,12 +688,18 @@
# Convert keyattr => { elem => '+attr' }
# to keyattr => { elem => [ 'attr', '+' ] }
- foreach (keys(%{$opt->{keyattr}})) {
- if($opt->{keyattr}->{$_} =~ /^(\+|-)?(.*)$/) {
- $opt->{keyattr}->{$_} = [ $2, ($1 ? $1 : '') ];
+ foreach my $el (keys(%{$opt->{keyattr}})) {
+ if($opt->{keyattr}->{$el} =~ /^(\+|-)?(.*)$/) {
+ $opt->{keyattr}->{$el} = [ $2, ($1 ? $1 : '') ];
+ if($StrictMode) {
+ next if($opt->{forcearray} == 1);
+ next if(ref($opt->{forcearray}) eq 'HASH'
+ and $opt->{forcearray}->{$el});
+ croak "<$el> set in keyattr but not in forcearray";
+ }
}
else {
- delete($opt->{keyattr}->{$_}); # Never reached (famous last words?)
+ delete($opt->{keyattr}->{$el}); # Never reached (famous last words?)
}
}
}
@@ -661,30 +714,10 @@
}
}
else {
- $opt->{keyattr} = [ @DefKeyAttr ];
- }
-
-
- # Special cleanup for {forcearray} which could be arrayref or boolean
- # or left to default to 0
-
- if(exists($opt->{forcearray})) {
- if(ref($opt->{forcearray}) eq 'ARRAY') {
- if(@{$opt->{forcearray}}) {
- $opt->{forcearray} = { (
- map { $_ => 1 } @{$opt->{forcearray}}
- ) };
- }
- else {
- $opt->{forcearray} = 0;
- }
- }
- else {
- $opt->{forcearray} = ( $opt->{forcearray} ? 1 : 0 );
+ if($StrictMode) {
+ croak "No value specified for 'keyattr' option in call to XML$dirn()";
}
- }
- else {
- $opt->{forcearray} = 0;
+ $opt->{keyattr} = [ @DefKeyAttr ];
}
@@ -906,6 +939,7 @@
delete $hashref->{$val}->{$key} unless($flag eq '+');
}
else {
+ croak "<$name> element has no '$key' key attribute" if($StrictMode);
carp "Warning: <$name> element has no '$key' key attribute" if($^W);
return($arrayref);
}
@@ -1504,6 +1538,9 @@
the same options, you might like to investigate L<"OPTIONAL OO INTERFACE">
below.
+If you can't be bothered reading the documentation, refer to
+L<"STRICT MODE"> to automatically catch common mistakes.
+
Because there are so many options, it's hard for new users to know which ones
are important, so here are the two you really need to know about:
@@ -1778,10 +1815,10 @@
any package elements to be folded on the 'id' attribute. No other elements
which have an 'id' attribute will be folded at all.
-Note: C<XMLin()> will generate a warning if this syntax is used and an element
-which does not have the specified key attribute is encountered (eg: a 'package'
-element without an 'id' attribute, to use the example above). Warnings will
-only be generated if B<-w> is in force.
+Note: C<XMLin()> will generate a warning (or a fatal error in L<"STRICT MODE">)
+if this syntax is used and an element which does not have the specified key
+attribute is encountered (eg: a 'package' element without an 'id' attribute, to
+use the example above). Warnings will only be generated if B<-w> is in force.
Two further variations are made possible by prefixing a '+' or a '-' character
to the attribute name:
@@ -1968,6 +2005,40 @@
escape_value method) or for building the initial parse tree (the build_tree
method).
+=head1 STRICT MODE
+
+If you import the B<XML::Simple> routines like this:
+
+ use XML::Simple qw(:strict);
+
+the following common mistakes will be detected and treated as fatal errors
+
+=over 4
+
+=item *
+
+Failing to explicitly set the keyattr option - if you can't be bothered reading
+about this option, turn it off with: keyattr => []
+
+=item *
+
+Failing to explicitly set the forcearray option - if you can't be bothered
+reading about this option, set it to the safest mode with: forcearray => 1
+
+=item *
+
+Setting forcearray to an array, but failing to list all the elements from the
+keyattr hash.
+
+=item *
+
+Data error - keyattr is set to say { part => 'partnum' } but the XML contains
+one or more E<lt>partE<gt> elements without a 'partnum' attribute (or nested
+element). Note: if strict mode is not set but -w is, this condition triggers a
+warning.
+
+=back
+
=head1 SAX SUPPORT
From version 1.08_01, B<XML::Simple> includes support for SAX (the Simple API
@@ -2090,35 +2161,35 @@
=item *
If the 'preferred parser' is set to the string 'XML::Parser', then
-B<XML::Parser> will be used (or C<XMLin()> will die if B<XML::Parser> is not
+L<XML::Parser> will be used (or C<XMLin()> will die if L<XML::Parser> is not
installed).
=item *
If the 'preferred parser' is set to some other value, then it is assumed to be
-the name of a SAX parser module and is passed to B<XML::SAX::ParserFactory.>
-If B<XML::SAX> is not installed, or the requested parser module is not
+the name of a SAX parser module and is passed to L<XML::SAX::ParserFactory.>
+If L<XML::SAX> is not installed, or the requested parser module is not
installed, then C<XMLin()> will die.
=item *
If the 'preferred parser' is not defined at all (the normal default
-state), an attempt will be made to load B<XML::SAX>. If B<XML::SAX> is
+state), an attempt will be made to load L<XML::SAX>. If L<XML::SAX> is
installed, then a parser module will be selected according to
-B<XML::SAX::ParserFactory>'s normal rules (which typically means the last SAX
+L<XML::SAX::ParserFactory>'s normal rules (which typically means the last SAX
parser installed).
=item *
if the 'preferred parser' is not defined and B<XML::SAX> is not
installed, then B<XML::Parser> will be used. C<XMLin()> will die if
-B<XML::Parser> is not installed.
+L<XML::Parser> is not installed.
=back
Note: The B<XML::SAX> distribution includes an XML parser written entirely in
Perl. It is very portable but it is not very fast. You should consider
-installing B<XML::LibXML> or B<XML::SAX::Expat> if they are available for your
+installing L<XML::LibXML> or L<XML::SAX::Expat> if they are available for your
platform.
=head1 ERROR HANDLING
@@ -2315,21 +2386,21 @@
XML::Parser's handler API - it is obselete).
For tree-based parsing, you could choose between the 'Perlish' approach of
-XML::Twig and more standards based DOM implementations - preferably one with
+L<XML::Twig> and more standards based DOM implementations - preferably one with
XPath support.
=head1 STATUS
-This version (1.09) is the current stable version.
+This version (2.00) is the current stable version.
=head1 SEE ALSO
-B<XML::Simple> requires either B<XML::Parser> or B<XML::SAX>.
+B<XML::Simple> requires either L<XML::Parser> or L<XML::SAX>.
-To generate documents with namespaces, B<XML::NamespaceSupport> is required.
+To generate documents with namespaces, L<XML::NamespaceSupport> is required.
-The optional caching functions require B<Storable>.
+The optional caching functions require L<Storable>.
=head1 COPYRIGHT
|