Keryn Drake
Keryn Drake

Reputation: 121

perl xml::libxml findvalue match

I am a complete newbie at perl and xml

I have data from two sources. One is book reviewers and their details, the other is reviews/

I need to get each reviewer, then for each reviewer get all of their reviews.

here is a simplified version of the data:

<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>
    </results>
</book_reviewers>

<book_reviews>
    <results>
        <review id="1">
            <title>First Book</title>
            <reviewed_by>Anne</reviewed_by>
            <rating>5</rating>
        </review>
        <review id="2">
            <title>First Book</title>
            <reviewed_by>Bob</reviewed_by>
            <rating>3</rating>
        </review>
        <review id="3">
            <title>Second Book</title>
            <reviewed_by>Charlie</reviewed_by>
            <rating>4</rating>
        </review>
        <review id="3">
            <title>Second Book</title>
            <reviewed_by>Anne</reviewed_by>
            <rating>4</rating>
        </review>
    </results>
</book_reviews>

Here is some code that i have tried

my $parser = new XML::LibXML;   
print "Couldn't retrieve review details\n" 
    unless my $book_reviews  = $parser->parse_file($reviews_file);

print "Couldn't retrieve critic details\n" 
    unless my $critic_details   = $parser->parse_file($critics_file);   

#extract the reviewers details and write to file
for my $critics ($critic_details->findnodes('/book_reviewers/results/reviewer')) {
    #get each of the critic's details
    my $name = $critics->findvalue('name');
    my $profession = $critics->findvalue('profession');
        for my $reviews($book_reviews->findnodes('book_reviews/results/review')){
            my $reviewed_by = $reviews->findvalue('reviewed_by');
                if ($reviewed_by eq $name ){
                    my $book =  $reviews->findvalue('title');
                    my $rating = $reviews->findvalue('rating');
                }
        }
}

What I am trying to do is:

  1. Iterate through each book_reviewer and get name. profession.

  2. For each book_reviewer got through the reviews and get all book_reviews for that book_reviewer and extract details about the reviews.

It will be displayed in a html table but i can do that, no problem.

At the moment it won't match the value of $reviewed_by and $critic - but it will if I had hard code the $critic value i.e. if ($reviewed_by eq 'Anne')

I have also tried

$byline->isSameNode($name );
$byline->isEqual($name );

and also

$query = "//review[bline/text() = $name ";

Any help appreciated - (and I cannot install any other modules - can only use the default ones) Cheers

Upvotes: 0

Views: 495

Answers (1)

John C
John C

Reputation: 4396

I suggest you turn on warnings and strict in your code.

use warnings;
use strict;

If you do that you will notice that the variable $critic is not being defined.

Another really useful trick for all kinds of perl problems is to include Data::Dumper.

use Data::Dumper

Then you can see what you have by printing stuff such as

print Dumper($critics);

Finally, after playing with your code a bit I think your main problem is the addresses you are using in your call to find nodes.

The first call you are using '/book_reviewer/results/reviewer' instead of '/book_reviewers/results/reviewer' and the second call you are using '/result_set/results/review' instead of '/book_reviews/results/review'. I plugged those in, added some print statements to see what was happening and it looks like it works.

for my $critics ($critic_details->findnodes('/book_reviewers/results/reviewer')) {
    #get each of the critic's details
    my $name = $critics->findvalue('name');
    print "Got Name: $name\n";
    my $profession = $critics->findvalue('profession');
    print "Got Profession: $profession\n";
    for my $reviews ($book_reviews->findnodes('/book_reviews/results/review')){
        print Dumper($reviews);
        my $reviewed_by = $reviews->findvalue('reviewed_by');
            print "Got reviewed_by: $reviewed_by\n";
            print "Compare $reviewed_by with $name\n";
            if ($reviewed_by eq $name ){
                print "Bingo!\n";
                my $book =  $reviews->findvalue('title');
                my $rating = $reviews->findvalue('rating');
            }
    }
}

Upvotes: 1

Related Questions