Ответ 1
Разница - это тип значения, возвращаемого методами.
-
findnodes
используется для возврата списка узлов. Если метод вызывается в контексте списка, он возвращает список объектов соответствующего типа, напримерXML::LibXML::Element
,XML::LibXML::Text
и т.д. Если он вызывается в скалярном контексте, он возвращает один объектXML::LibXML::NodeList
, который содержит та же информация.Он не может использоваться для возврата произвольного выражения, например
$dom->findnodes('42')
ничего не вернет. Вы можете получать только узлы списка документов из этого метода. -
findvalue
используется для возврата одного текстового или числового значения, т.е. не XML node. Если вы передадите выражение XPath, которое оценивает список node, тогда он преобразует этот список в текст, объединяя все текстовые узлы в любом из узлов в списке. -
find
может вернуть что угодно. Он вернет список node как объектXML::LibXML::NodeList
, числовое значение как объектXML::LibXML::Number
, строковый литерал как объектXML::LibXML::Literal
и т.д. В отличие отfindnodes
, он всегда возвращает одно скалярное значение, даже если вызывается в контексте списка.Я никогда не выбирал использовать
find
. Похоже, он предназначен для всех, когда вы не знаете, какого результата ожидать.
Например, вы, вероятно, захотите написать my $nrecs = $dom->findvalue('count(/root/record)')
, чтобы получить количество записей в корневом элементе. $nrecs
будет простым числовым значением perl.
С другой стороны, чтобы получить список этих записей, вы должны использовать my @records = $dom->findnodes('/root/record')
. Теперь @records
содержит несколько объектов XML::LibXML::Element
.
В ваших примерах
my $node_cnt = $dom->findvalue("count($xpath_str)"); # WORKS!
это устанавливает $node_cnt
в простое число Perl, а это
my $node_cnt = $dom->find("count($xpath_str)"); # WORKS!
устанавливает $node_cnt
в объект XML::LibXML::Number
, который, как правило, строит (когда вы печатаете его) так же, как и предыдущий оператор. Докажите это сами, напечатав print ref $node_cnt
в обоих случаях.
Тогда
my @node_cnt = $dom->findnodes("count($xpath_str)"); # count doesn't work!
терпит неудачу, потому что XPath count
оценивается числом, а не XML node (он не является частью дерева XML). Нет способа преобразования чисел в узлы, поэтому результат представляет собой пустой список. Если бы это было наоборот, и мы вызывали findvalue
в выражении, которое оценивалось в списке node, тогда есть неопределенно разумный способ преобразования в текстовое значение, а findvalue
делает все возможное и возвращает конкатенация всех текстовых узлов, содержащихся в узлах в списке.