如何读取节点中的XML在Perl中具有值

时间:2015-07-03 09:19:36

标签: xml perl

我有一个像这样的简单xml

<Rows><Row name="23"><product_id>23</product_id><product_name>Final
Fantasy</product_name><Row>
.
.
.
<Row name="25"><product_id>25</product_id><product_name>Final
</product_name><Row>
<Rows>

我有这样的代码:

use strict;
use XML::Simple;
my $source = XMLin("$source_of_file");

    my $v = $source->{Row};

    if($v && ref($v) eq 'ARRAY'){
        my @v = @{$v};
        foreach my $object(@v) {
                my %data = %{$object};
                my $id = $data{product_id};
                print $id;

                my $title;
                unless (ref($data{product_name}) eq 'HASH') {
                    $title  = $data{product_name};
                }
                print $title;

        .....
        }
     }

我想得到这样的输出:

23
Final Fantasy
...
25
Final

您能帮我获取XML数据吗?我不知道。

2 个答案:

答案 0 :(得分:2)

好的,所以 - XML::Simple谎言。这并不简单。它是 for 简单的XML。它基本上是可怕的,不要使用它。

  

“不鼓励在新代码中使用此模块。其他模块可用,提供更直接,更一致的接口。”

我建议改为XML::Twig

#!/usr/bin/env perl
use strict;
use warnings;

use XML::Twig; 

my $twig = XML::Twig -> new ( 'pretty_print' => 'indented_a', 
                              'twig_handlers' => { 'Row' => sub { $_ -> print } } );
$twig -> parsefile ( "yourXmlFile.xml" );

##print the whole thing, formatted:
$twig -> print; 

这样的事情。如果您可以提供所需的输入/输出,那么我们可以为您提供更好的工作示例。

编辑:根据您给出的示例:

#!/usr/bin/env perl
use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig->new(
    'pretty_print'  => 'indented_a',
    'twig_handlers' => {
        'Row' => sub {
            print $_ ->first_child_text('product_id'),   "\n";
            print $_ ->first_child_text('product_name'), "\n";
        }
    }
);
$twig->parsefile("yourXmlFile.xml");

虽然注意 - 我必须纠正你的XML。如果这是因为你的打字问题(而且我认为是因为点数)那很好。另一方面,如果你破坏了XML,那么你就会被打破,因为破解的XML 假定是致命的,任何解析它们的东西都应该来破坏。< / p>

Dealing with malformed XML

XML::Twig允许您设置每次看到特定元素时调用的处理程序。所以在上面的例子中,它就像'print every Row元素一样简单。

但您可以将其设置为子程序:

'twig_handlers' => { 'Row' => \&process_row }

然后有一个更详细的处理程序:

sub process_row {
     my ( $twig, $row ) = @_; 
     print $row -> att{'name'},"\n";
     print $row -> first_child('product_name')->text,"\n";
}

您还可以使用xpath查找XML中的元素:

my $row23 = $twig -> get_xpath ( 'row[@name="23"]', 0 ); 
$row23 -> print; 

答案 1 :(得分:2)

我喜欢XML::LibXML来处理XML。

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

use XML::LibXML;

my $parser = XML::LibXML->new();
my $doc = $parser->parse_fh(*DATA);

foreach ($doc->findnodes('//Row')) {
  say $_->findvalue('product_id');
  say $_->findvalue('product_name');
}

__END__
<Rows><Row name="23"><product_id>23</product_id><product_name>Final
Fantasy</product_name></Row>
<Row name="25"><product_id>25</product_id><product_name>Final
</product_name></Row>
</Rows>

您提供给我们的示例不是有效的XML。一些结束标签不正确。如果您需要我们的帮助,请将数据粘贴到您的问题中 - 请勿尝试重新输入。