Search code examples
xmlperlxml-libxml

Perl XML::LibXML getting the Nth element


Here is some simplified sample xml

<book_reviewers>
    <results>
        <reviewer>
            <name>Anne</name>
            <profession>Catfish wrangler</profession>
        </reviewer>
        <reviewer>
            <name>Bob</name>
            <profession>Beer taster</profession>
        </reviewer>
        <reviewer>
            <name>Charlie</name>
            <profession>Gardener</profession>
        </reviewer>
        <reviewer>
            <name>Don</name>
            <profession>DoGooder</profession>
        </reviewer>
        <reviewer>
            <name>Ellie</name>
            <profession>Elephant Trainer</profession>
        </reviewer>
        <reviewer>
            <name>Freddy</name>
            <profession>Fencer</profession>
        </reviewer>
    </results>
</book_reviewers>

Them i parse the data

#!/usr/bin/perl
use XML::LibXML;
use strict;

my $filename = "cr.xml";

my $parser = XML::LibXML->new();
my $critic_details = $parser->parse_file("$filename") or die;

Now I want to grab the details of a random reviewer

my $no_of_critics = ($critic_details->findvalue("count(/book_reviewers/results/reviewer)"));

I send number 1 and $no_of_critics off to a subroutine that returns a random number between one and $no_of_critics (i.e. n this case 1 and 6)

All of this works fine I just need to know how I tell it which reviewer - say it returns 5, then how do I tell it I want the fifth occurrence of reviewer? I have tried searching but I cannot get the right search term so I am a bit stuck

Cheers


Solution

  • Building on top of what yu already had in your previous question:

    use strict;
    use warnings;
    
    use utf8;
    
    use XML::LibXML;
    
    my $filename = "cr.xml";
    
    my $parser = XML::LibXML->new();
    my $critic_details = $parser->parse_file("$filename") or die;
    
    # find ALL the <book_reviewers><results><reviewers> nodes
    my @reviewers = $critic_details
      ->findnodes("book_reviewers/results/reviewer");
    die "no reviewer nodes in xml-file" unless @reviewers;
    
    # @reviewers in scalar context gives the number of elements
    my $reviewer = $reviewers[ rand @reviewers ];
    
    printf "reviewer: %s (%s)\n",
      $reviewer->findvalue("name"),
      $reviewer->findvalue("profession"),
      ;
    
    __END__
    

    which could result in:

    reviewer: Anne (Catfish wrangler)
    

    enjoy!