2010-01-10 9 views
5

Tôi gặp sự cố khi hiểu/sử dụng không gian tên với gói XML::LibXML trong Perl. Tôi có thể truy cập thành phần nhưng không phải thuộc tính. Tôi có đoạn mã sau để truy cập một tập tin XML (http://pastebin.com/f3fb9d1d0).Làm cách nào để truy cập các thuộc tính và phần tử từ XML :: LibXML trong 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'); 

Sau đó, tôi thử truy cập phần tử được gọi là tên thường gọi và thuộc tính được gọi là tên.

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" ; 
} 

Nhưng chỉ có tên latin (@name) được in ra, tên chung thì không. Tôi đang làm gì sai và làm thế nào tôi có thể nhận được tên chung để in ra?

@name làm gì trong trường hợp này? Tôi đoán nó là một mảng, và các thuộc tính đó nên được đưa vào một mảng vì có thể có nhiều hơn một, nhưng các phần tử (như tên chung) không nên là vì chỉ nên có một?

Tôi đã làm theo các ví dụ tại đây: http://www.xml.com/pub/a/2001/11/14/xml-libxml.html và tại đây: http://perl-xml.sourceforge.net/faq/#namespaces_xpath và cố gắng lấy tập lệnh lạc đà mẫu làm việc với không gian tên của tôi, do đó không gian tên lạ.

Trả lời

6

Đảm bảo tệp XML của bạn hợp lệ, sau đó sử dụng $node->getAttribute("someAttribute") để truy cập các thuộc tính.

@name là tên thuộc tính. Bạn sẽ sử dụng nó trong findnodes() để chỉ định các phần tử với một tập hợp thuộc tính đã cho. Ví dụ. một con đường như:

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

Đây là một đơn giản/contrived dụ:

#!/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"; 
    } 
} 

Output là:

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

Cảm ơn Niels, tôi có câu hỏi ban đầu của tôi một cách sai lầm xung quanh, tên latin (@name) đã được in ra tốt, tên thông thường thì không. Không chắc chắn nếu điều đó thay đổi câu trả lời của bạn. Tôi đã thử ví dụ của bạn nhưng tôi không thể in được gì cả. Vấn đề tôi gặp phải là phải làm nhiều hơn với không gian tên mà tôi nghĩ. Nếu tôi không sử dụng hai dòng không gian tên đầu tiên (với $ xpc trong chúng) và chỉ tham khảo các elemtents như ví dụ ở đây http://www.xml.com/pub/a/2001/11/14/xml-libxml .html thì mọi thứ đều ổn, nhưng khi tôi bao gồm không gian tên, nó không hoạt động, bằng cách nào đó tôi không nhận được elementIwant – John

+0

Tôi đã xóa không gian tên và cân bằng các thẻ trong tệp XML mà bạn đang đề cập để chạy ví dụ. Tôi sẽ thêm không gian tên vào ví dụ. –

+0

Tôi đã cập nhật tệp XML của bạn tại pastebin http://pastebin.com/f3fb9d1d0 –