2010-01-10 18 views
5

Tengo problemas para entender/usar espacios de nombres con el paquete XML::LibXML en Perl. Puedo acceder a un elemento con éxito pero no a un atributo. Tengo el siguiente código que accede a un archivo XML (http://pastebin.com/f3fb9d1d0).¿Cómo puedo acceder a los atributos y elementos de XML :: LibXML en Perl?

my $tree = $parser->parse_file($file); # parses the file contents into the new libXML object. 
my $xpc = XML::LibXML::XPathContext->new($tree); 
$xpc->registerNs(microplateML => 'http://moleculardevices.com/microplateML'); 

Luego trato de acceder a un elemento llamado nombre común y un atributo llamado nombre.

foreach my $camelid ($xpc->findnodes('//microplateML:species')) { 
    my $latin_name = $camelid->findvalue('@name'); 
    my $common_name = $camelid->findvalue('common-name'); 
    print "$latin_name, $common_name" ; 
} 

Pero sólo el nombre latino (@name) está imprimiendo, el nombre común no lo es. ¿Qué estoy haciendo mal y cómo puedo obtener el nombre común para imprimir también?

¿Qué hace @name en este caso? Supongo que es una matriz, y que los atributos se deben poner en una matriz, ya que puede haber más de uno, pero los elementos (como el nombre común) no deberían ser porque simplemente debería haber uno.

He estado siguiendo los ejemplos aquí: http://www.xml.com/pub/a/2001/11/14/xml-libxml.html y aquí: http://perl-xml.sourceforge.net/faq/#namespaces_xpath, y tratando de conseguir su script de ejemplo camello trabajando con mi espacio de nombres, por lo tanto, el espacio de nombre raro.

Respuesta

6

Asegúrate de que el archivo XML sea válido y luego usa $node->getAttribute("someAttribute") para acceder a los atributos.

@name es un nombre de atributo. Lo usarías en findnodes() para especificar elementos con un determinado conjunto de atributos. P.ej. un camino como:

//camelids/species[@name="Camelus bactrianus"]/

Aquí está un ejemplo simple/artificial:

#!/usr/bin/perl -w 
use XML::LibXML; 

my $parser = XML::LibXML->new(); 
my $doc = $parser->parse_file('/Users/castle/Desktop/animal.xml'); 

my $xc = XML::LibXML::XPathContext->new($doc->documentElement() ); 
$xc->registerNs('ns', 'http://moleculardevices.com/microplateML'); 

my @n = $xc->findnodes('//ns:species'); 
foreach $nod (@n) { 
    print "A: ".$nod->getAttribute("name")."\n"; 

    my @c = $xc->findnodes("./ns:common-name", $nod); 
    foreach $cod (@c) { 
     print "B: ".$cod->nodeName; 
     print " = "; 
     print $cod->getFirstChild()->getData()."\n"; 
    } 
} 

de salida es:

perl ./xmltest.pl 
A: Camelus bactrianus 
B: common-name = Bactrian Camel 
+0

Gracias Niels, tengo mi pregunta original al revés, el nombre latino (@name) estaba imprimiendo bien, el nombre común no. No estoy seguro de si eso cambia tu respuesta. Intenté tu ejemplo, pero no pude imprimir nada. El problema que estoy teniendo es más que ver con el espacio de nombres, creo. Si no utilizo las primeras dos líneas del espacio de nombres (con $ xpc en ellas) y solo hago referencia a los elementos como los ejemplos aquí http://www.xml.com/pub/a/2001/11/14/xml-libxml .html entonces todo está bien, pero cuando incluyo el espacio de nombres, no funciona, de alguna manera no obtengo el elementoIwant – John

+0

Quité el espacio de nombres y equilibré las etiquetas en el archivo XML al que se refería para hacer que el ejemplo se ejecute. Agregaré el espacio de nombres al ejemplo. –

+0

Actualicé su archivo XML en pastebin http://pastebin.com/f3fb9d1d0 –

Cuestiones relacionadas