Good question! This is not (yet!) documented, but the expat object, which gives you access to all of the Expat methods, including the current line and column numbers can be accessed through the twig: it is in $t->{twig_parser}. So getting t->{twig_parser}->current_line will give you the current line number. There is one caveat though: twig_handlers are called when an element is completely parsed (so you can process its content), so you will get the position of the closing tag, which is of course enough to locate the element, but might not be the most convenient way to then edit the document. So you might want to "annotate" the document with the position for each tag, or at least each tag in which you are interested.
By the way, XML::Parser::Expat, which calls Expat to actually reading the XML, does not set $. so you can't use it.
So here is a version that properly outputs the line/column number for the opening element. If the line/number for the closing element is OK then you don't need the start_tag_handler and you can get the position in the elt handler, and if you are concerned about size you might want to limit calls to the start_tag_handler to those elements that you check late.
#!/bin/perl -w use strict; use XML::Twig; my $t= new XML::Twig( # called for all opening tags start_tag_handlers => { _all_ => \&store_position }, # called for each closing elt tag twig_handlers => { elt => \&elt}); $t->parse( \*DATA); sub store_position { my( $t, $elt)= @_; my $line = $t->{twig_parser}->current_line; # $t->{tw +ig_parser} is the expat object my $column = $t->{twig_parser}->current_column; $elt->{my_atts}= { line => $line, column => $column }; # crude b +ut works } sub elt { my( $t, $elt)= @_; if( my $error= $elt->att( 'error')) { my $line = $elt->{my_atts}->{line}; my $column = $elt->{my_atts}->{column}; print STDERR "error $error at $line:$column\n"; } } __DATA__ <doc> <elt>this one is OK</elt> <elt error="foo">not this one though</elt> <elt>OK</elt> <elt error="bar">here is a bar error</elt> </doc>
By the way, I have a question on this last piece of code: in order to store the position information I simply use a new field in the hash (my_atts). This is convenient but hardly robust: what if the object implementation changes to a blessed scalar or a closure? Or if it uses a "my_atts" field? What would be a better way? Inheritance seems difficult, as the elements are created and processed by XML::Twig. Should XML::Twig document a field that can be used for this, both for twigs and for elements?
In reply to Re: XML::Twig error reporting
by mirod
in thread XML::Twig error reporting
by John M. Dlugosz
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |