Perl XML:: LibXML: findnode vs. findvalue vs. find - Quelle est la différence?

j'utilise XML::LibXML, et j'ai simplement besoin de compter les noeuds spécifiés par une expression XPath.

L'utilisation de l'une ou l'autre des deux premières lignes de code ci-dessous donne ce que je cherche. Je peux utiliser le count fonction XPath avec l'une ou l'autre findvalue ou find mais pas findnodes (oui, je sais, parce qu'elle renvoie une liste).

my $node_cnt = $dom->findvalue("count($xpath_str)");  # WORKS!
my $node_cnt = $dom->find("count($xpath_str)");       # WORKS!
my @node_cnt = $dom->findnodes("count($xpath_str)");  # count doesn't work!

ce qui m'amène à une question générale lancinante: Quelle est la différence entre les trois types? Dans le de la documentation, il dit:

$string = $node->findvalue($xpath)
$result = $node->find($xpath)
@nodes  = $node->findnodes($xpath_expression)
  1. Est-il vraiment une différence entre l'argument $xpath_expression vs $xpath dans la documentation?

  2. pour les deux retournant un scalaire, Quelle est la différence?

j'essaie de comprendre la signification de l'utilisation d'un type de find par rapport à l'autre - merci!

12
demandé sur Borodin 2013-11-06 19:54:23

1 réponses

la différence est le type de valeur que les méthodes renvoient.

  • findnodes est utilisée pour retourner une liste de nœuds. Si la méthode est appelée dans le contexte list, alors elle renvoie une liste d'objets du type approprié, tels que XML::LibXML::Element,XML::LibXML::Text etc. Si elle est appelée dans le contexte scalaire, elle renvoie un XML::LibXML::NodeList objet qui contient les mêmes informations.

    ne peut pas être utilisé pour renvoyer une expression arbitraire, par exemple $dom->findnodes('42') retournera rien. Vous ne pouvez obtenir qu'une liste des noeuds de documents à partir de cette méthode.

  • findvalue est utilisé pour retourner un texte simple ou numérique valeur, c'est-à-dire pas un noeud XML. Si vous passez une expression XPath qui évalue à une liste de noeuds, alors elle convertit cette liste en texte en concaténant tous les noeuds de texte dans n'importe lequel des noeuds de la liste.

  • find peut rapporter n'importe quoi. Il retournera une liste de noeuds comme un XML::LibXML::NodeList objet, une valeur numérique comme un XML::LibXML::Number objet, une chaîne littérale comme un XML::LibXML::Literal objet etc. Contrairement à findnodes,toujours renvoie une seule valeur scalaire, même si elle est appelée dans le contexte list.

    je n'ai jamais choisi d'utiliser find. Il semble qu'il est prévu comme un piège tous quand vous ne savez pas quel genre de résultat à attendre.

Par exemple, vous auriez probablement eu envie d'écrire my $nrecs = $dom->findvalue('count(/root/record)') pour obtenir le nombre d'enregistrements dans la racine élément. $nrecs serait une valeur numérique perl simple.

d'autre part, pour obtenir un liste de ces enregistrements, vous utiliseriez my @records = $dom->findnodes('/root/record'). Maintenant @records contient un nombre de XML::LibXML::Element objets.

dans vos exemples,

my $node_cnt = $dom->findvalue("count($xpath_str)");  # WORKS!

jeux $node_cnt à un nombre Perl simple, alors que celui-ci

my $node_cnt = $dom->find("count($xpath_str)");  # WORKS!

configure $node_cntXML::LibXML::Number de l'objet, ce qui arrive à stringify (lors de l'impression) de la même manière que la précédente déclaration. Prouver vous-même en impression print ref $node_cnt dans les deux cas.

my @node_cnt = $dom->findnodes("count($xpath_str)");  # count doesn't work!

échoue parce que le XPath count évalue à un nombre, pas à un noeud XML (il ne fait pas partie de L'arborescence XML). Il n'y a aucun moyen de convertir des nombres en noeuds, donc le résultat est une liste vide. Si c'était l'inverse, et nous avions appelé findvalue sur une expression évaluée à une liste de noeuds, alors il y a une façon vaguement sensible de convertir en valeur texte et findvalue fait de son meilleur et renvoie la concaténation de tous les nœuds de texte contenue par les noeuds de la liste.

17
répondu Borodin 2013-11-06 16:55:02