I like XPath and found some XPath solutions to the problem on stackoverflow here including this one: //*[not(child::*)].
XML::Twig didn't seem to handle the XPath expressions on stackoverflow but XML::XPath did. XML::XPath also comes with an 'xpath' grep like utility that might give you a solution as simple as:
xpath -e '//*[not(child::*)]' books.xml
If you want to do Perl coding for further processing the solution is still pretty simple
use strict;
use warnings;
use XML::XPath;
use XML::XPath::XMLParser;
my $xp = XML::XPath->new(filename => 'books.xml');
my $nodeset = $xp->find('//*[not(child::*)]');
foreach my $node ($nodeset->get_nodelist) {
print "FOUND:",
XML::XPath::XMLParser::as_string($node),
"\n";
}