【问题标题】:How can I access attributes and elements from XML::LibXML in Perl?如何在 Perl 中从 XML::LibXML 访问属性和元素?
【发布时间】:2011-01-03 14:13:57
【问题描述】:

我在 Perl 中无法理解/使用带有 XML::LibXML 包的名称空间。我可以成功访问元素但不能访问属性。我有以下代码可以访问 XML 文件 (http://pastebin.com/f3fb9d1d0)。

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');   

然后我尝试访问一个名为 common-name 的元素和一个名为 name 的属性。

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

但只有拉丁名 (@name) 打印出来,通用名没有。我做错了什么,如何才能打印出通用名称?

@name 在这种情况下有什么作用?我认为它是一个数组,应该将属性放入一个数组中,因为可以有多个,但元素(如 common-name)不应该因为应该只有一个?

我一直在关注这里的示例:http://www.xml.com/pub/a/2001/11/14/xml-libxml.html 在这里:http://perl-xml.sourceforge.net/faq/#namespaces_xpath,并试图让他们的示例骆驼脚本与我的命名空间一起使用,因此是奇怪的命名空间。

【问题讨论】:

    标签: perl xpath namespaces libxml2 xml-libxml


    【解决方案1】:

    确保您的 XML 文件有效,然后使用 $node->getAttribute("someAttribute") 访问属性。

    @name 是一个属性名称。您可以在 findnodes() 中使用它来指定具有给定属性集的元素。例如。像这样的路径:

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

    这是一个简单/人为的例子:

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

    输出是:

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

    【讨论】:

    • 谢谢 Niels,我原来的问题弄错了,拉丁名 (@name) 打印得很好,通用名不是。不确定这是否会改变您的答案。我尝试了您的示例,但根本无法打印任何内容。我遇到的问题更多与我认为的命名空间有关。如果我不使用前两个命名空间行(其中包含 $xpc)并且只引用这里的示例 xml.com/pub/a/2001/11/14/xml-libxml.html 中的元素,那么一切都很好,但是当我包含命名空间时,它不起作用,不知何故我'我没有得到 elementIwant
    • 我删除了命名空间并平衡了您所指的 XML 文件中的标签,以使示例运行。我会将命名空间添加到示例中。
    • 再次感谢 Neils,我认为 xml 文件中还有另一个错误,这一行应该是第一个 ()我修复了它(pastebin.com/f63e6d7a3)并尝试运行上面的示例脚本(感谢您这样做),但我根本没有从脚本中得到任何输出。你试过运行它吗?这条线似乎不起作用我的 @n = $xc->findnodes('*/species');你知道为什么它不工作吗?谢谢。
    • 我重新问了这个特定的问题并得到了我应该使用这个的答案:my @n = $xc->findnodes('//ns:species');现在有效。再次感谢。 stackoverflow.com/questions/2079435/…
    • 伙计,这很尴尬。我在使用粘贴板时从 XML 文件中删除了命名空间声明,并在运行 Perl 脚本之前忘记再次添加它。你的评论当然是正确的。我将它添加到示例脚本中。粘贴板上的 XML 仍然不平衡,您需要添加一个结束。干杯,伙计!
    猜你喜欢
    • 2013-08-17
    • 1970-01-01
    • 2013-07-15
    • 2014-07-06
    • 2020-08-05
    • 2012-04-13
    • 2017-01-15
    • 2010-09-07
    • 1970-01-01
    相关资源
    最近更新 更多