) { my $method = sub { $_[0]{$field} }; no strict 'refs'; *$field = $method; } { sub new { my ($class,$xE) = @_; my $terr; if (ref($xE)) { my ($context,$column) = $xE->context_and_column(); $terr =bless { domain => $xE->domain(), level => $xE->level(), code => $xE->code(), message => $xE->message(), file => $xE->file(), line => $xE->line(), str1 => $xE->str1(), str2 => $xE->str2(), str3 => $xE->str3(), num1 => $xE->num1(), num2 => $xE->num2(), __prev_depth => 0, (defined($context) ? ( context => $context, column => $column, ) : ()), }, $class; } else { # !!!! problem : got a flat error # warn("PROBLEM: GOT A FLAT ERROR $xE\n"); $terr =bless { domain => 0, level => 2, code => -1, message => $xE, file => undef, line => undef, str1 => undef, str2 => undef, str3 => undef, num1 => undef, num2 => undef, __prev_depth => 0, }, $class; } return $terr; } sub _callback_error { #print "CALLBACK\n"; my ($xE,$prev) = @_; my $terr; $terr=XML::LibXML::Error->new($xE); if ($terr->{level} == XML_ERR_WARNING and $WARNINGS!=2) { warn $terr if $WARNINGS; return $prev; } #unless ( defined $terr->{file} and length $terr->{file} ) { # this would make it easier to recognize parsed strings # but it breaks old implementations # [CG] $terr->{file} = 'string()'; #} #warn "Saving the error ",$terr->dump; if (ref($prev)) { if ($prev->__prev_depth() >= $MAX_ERROR_PREV_DEPTH) { return $prev; } $terr->{_prev} = $prev; $terr->{__prev_depth} = $prev->__prev_depth() + 1; } else { $terr->{_prev} = defined($prev) && length($prev) ? XML::LibXML::Error->new($prev) : undef; } return $terr; } sub _instant_error_callback { my $xE = shift; my $terr= XML::LibXML::Error->new($xE); print "Reporting an instanteous error ",$terr->dump; die $terr; } sub _report_warning { my ($saved_error) = @_; #print "CALLBACK WARN\n"; if ( defined $saved_error ) { #print "reporting a warning ",$saved_error->dump; warn $saved_error; } } sub _report_error { my ($saved_error) = @_; #print "CALLBACK ERROR: $saved_error\n"; if ( defined $saved_error ) { die $saved_error; } } } # backward compatibility sub int1 { $_[0]->num1 } sub int2 { $_[0]->num2 } sub domain { my ($self)=@_; return undef unless ref($self); my $domain = $self->{domain}; # Newer versions of libxml2 might yield errors in domains that aren't # listed above. Invent something reasonable in that case. return $domain < @error_domains ? $error_domains[$domain] : "domain_$domain"; } sub as_string { my ($self)=@_; my $msg = ""; my $level; if (defined($self->{_prev})) { $msg = $self->{_prev}->as_string; } if ($self->{level} == XML_ERR_NONE) { $level = ""; } elsif ($self->{level} == XML_ERR_WARNING) { $level = "warning"; } elsif ($self->{level} == XML_ERR_ERROR || $self->{level} == XML_ERR_FATAL) { $level = "error"; } my $where=""; if (defined($self->{file})) { $where="$self->{file}:$self->{line}"; } elsif (($self->{domain} == XML_ERR_FROM_PARSER) and $self->{line}) { $where="Entity: line $self->{line}"; } if ($self->{nodename}) { $where.=": element ".$self->{nodename}; } $msg.=$where.": " if $where ne ""; $msg.=$self->domain." ".$level." :"; my $str=$self->{message}||""; chomp($str); $msg.=" ".$str."\n"; if (($self->{domain} == XML_ERR_FROM_XPATH) and defined($self->{str1})) { $msg.=$self->{str1}."\n"; $msg.=(" " x $self->{num1})."^\n"; } elsif (defined $self->{context}) { # If the error relates to character-encoding problems in the context, # then doing textual operations on it will spew warnings that # XML::LibXML can do nothing to fix. So just disable all such # warnings. This has the pleasing benefit of making the test suite # run warning-free. no warnings 'utf8'; my $context = Encode::encode('utf8', $self->{context}, Encode::FB_DEFAULT); $msg.=$context."\n"; $context = substr($context,0,$self->{column}); $context=~s/[^\t]/ /g; $msg.=$context."^\n"; } return $msg; } sub dump { my ($self)=@_; use Data::Dumper; return Data::Dumper->new([$self],['error'])->Dump; } 1;