Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I have a xml file like this(pasted only a part of the xml)
<bitrate name="1000"> <track type="V"> <range> <rangeStartTime>1261287</range +StartTime> <rangeEndTime>1324271</rangeEn +dTime> </range> <range> <rangeStartTime>1324282</range +StartTime> <rangeEndTime>0.000</rangeEndT +ime> </range> </track> </bitrate>
I want to extract the value of 1st rangeStartTime
my $twig = XML::Twig->new( twig_roots => { "bitrate[\@name=\"1000\"]/trac +k[\@type=\"V\"]/range[1]/rangeStartTime" => \&update, }, ) ->parse($filename); print $value; sub update { my ($twig, $server) = @_; $value= $server->text; }
This gives me the 2nd rangeStartTime in the xml.

If i use the xpath like
"bitrate[\@name=\"1000\"]/track[\@type=\"V\"]/range[position() = 1]/ra +ngeStartTime"
I get an error
"unrecognized expression in handler: 'bitrate[@name="1000"]/track[@typ +e="V"]/range[position() = 1]/rangeStartTime' at try16.pl line 35"
I tried to use findnode() also
my $count = $t->findnodes("bitrate[\@name=\"1000\"]/track[\@type=\"V\" +]/range[position() = 1]/rangeStartTime");
It gives error like this
error in xpath expression bitrate[@name="1000"]/track[@type="V"]/range +[position() = 1]/rangeStartTime at position() = 1 at /usr/share/perl5 +/XML/Twig.pm line 3085
I have xml::xpath installed on my system
I am stuck on this for quite a while, any help would be appreciated.

Extra code tags added by GrandFather

Replies are listed 'Best First'.
Re: XML::Twig - Using xpath with twig roots
by choroba (Cardinal) on Dec 19, 2011 at 12:47 UTC
    As documented, Twig does not support full XPath for handlers. Either create a flag that prevents processing of the 2nd and following occurences, or use a different module to handle XML that supports XPath (as XML::LibXML::Reader).
    Update :An example using my favourite XML handling module, XML::XSH2:
    open 944240.xml ; echo /bitrate[@name="1000"]/track[@type="V"]/range[1]/rangeStartTime ;
      Thanks. Does findnodes() also not support the full Xpath? I see references that it does, but somehow it doesnt work for me.

        According to this post, findnodes() uses the full XPath engine. Also, I noticed that the use of position selectors like range[1] isn't supported on twig_handlers or twig_roots.

        Since you're dealing with a very, very small XML, I tried this and returned both rangeStartTimes. I cheated:)...
        #!/usr/bin/perl -l use strict; use warnings; use XML::Twig::XPath; $|=1; my $file = '/root/Desktop/bitrate.xml'; my $twig = XML::Twig::XPath->new( twig_roots => { "//range/rangeStartTime" => \&update }); $twig->parsefile($file); sub update { my ($twig, $server) = @_; print $server->text; }
        Here's the tidied XML:
        <?xml version="1.0" encoding="UTF-8"?> <bitrate name="1000"> <track type="V"> <range> <rangeStartTime>1261287</rangeStartTime> <rangeEndTime>1324271</rangeEndTime> </range> <range> <rangeStartTime>1324282</rangeStartTime> <rangeEndTime>0.000</rangeEndTime> </range> </track> </bitrate>
        Update: fixed typo