0

The findvalue function in HTML::TreeBuilder::XPath returns a concatenation of any values found by the xpath query.

Why does it do this, and how could a concatenation of the values be useful to anyone?

CJ7
  • 22,579
  • 65
  • 193
  • 321

2 Answers2

2

Why does it do this?

When you call findvalue, you're requesting a single scalar value. If there are multiple matches, they have to be combined into a single value somehow.

From the documentation for HTML::TreeBuilder::XPath:

findvalue ($path)

...If the path returns a NodeSet, $nodeset->xpath_to_literal is called automatically for you (and thus a Tree::XPathEngine::Literal is returned).

And from the documentation for Tree::XPathEngine::NodeSet:

xpath_to_literal()

Returns the concatenation of all the string-values of all the nodes in the list.

An alternative would be to return the Tree::XPathEngine::NodeSet object so the user could iterate through the results himself, but the findvalues method already returns a list.


How could a concatenation of the values be useful to anyone?

For example:

use strict;
use warnings 'all';
use 5.010;

use HTML::TreeBuilder::XPath;

my $content = do { local $/; <DATA> };
my $tree = HTML::TreeBuilder::XPath->new_from_content($content);

say $tree->findvalue('//p');

__DATA__
<p>HTML is just text.</p>
<p>It can still make sense without the markup.</p>

Output:

HTML is just text.It can still make sense without the markup.

Usually, though, it makes more sense to get a list of matches and iterate through them instead of doing dumb concatenation, so you should use findvalues (plural) if you could have multiple matches.

Community
  • 1
  • 1
ThisSuitIsBlackNot
  • 23,492
  • 9
  • 63
  • 110
  • The more sensible behaviour would be for it to return the first match in a scalar context and all matches in a list context, which is what other modules do, eg. `look_down` in `HTML::Element`. – CJ7 Jul 12 '16 at 09:50
  • 2
    No. It shouldn't return something other than what you asked for. If you just want the first one, ask for just the first one – ikegami Jul 12 '16 at 11:02
  • @ikegami So are you saying `look_down` in `HTML::Element`is wrong? – CJ7 Jul 12 '16 at 22:46
  • @ikegami So what is your opinion on `look_down` in `HTML::Element`? It returns the first match in a scalar context and all matches in a list context. – CJ7 Jul 13 '16 at 01:59
  • @ikegami In the second comment to this answer you said it shouldn't do that. – CJ7 Jul 13 '16 at 02:01
  • @ikegami I'm not sure why you would want to defend what is quite an odd and unusable feature of the function. – CJ7 Jul 13 '16 at 02:05
  • @ikegami What I'm saying is that a concatenation is close to useless in most cases. – CJ7 Jul 13 '16 at 02:10
  • @ikegami In my opinion a function that concatenates all the values should be a separate function because it is an unusual requirement. There should simply be a `findvalues` function that returns the first match in a scalar context and all matches in a list context. – CJ7 Jul 13 '16 at 02:25
  • @ikegami If it is "a totally redundant function" then why does `look_down` in `HTML::Element` do what I am asking for? – CJ7 Jul 14 '16 at 01:04
1

Use

( $tree->findvalues('//p') )[0] ;

instead.

Alex
  • 45
  • 4