Perl, XML::Twig, how to reading field with the same tag

冷暖自知 提交于 2019-12-05 08:11:53

If you want the handlers for type, name and desctiption only be triggered in the object tag, specify the path:

my $twig = new XML::Twig( twig_handlers => { 
                 id                    => \&get_ID,
                 'object/name'         => \&get_Name,
                 'object/type'         => \&get_Type,
                 'object/description'  => \&get_Description,
                 localcosts            => \&get_Localcosts
    });

The problem is that the id, name, type and description handlers are being executed for both occurrences. You will find that the contents of the @fields is from the localcost values, as the data from the object values has been overwritten.

Also, in handling the localcost elements, the handlers have done a $twig->purge, which removes the data from memory. So when the localcosts handler is called it finds the element empty

I think the easiest way to do this is to write a single handler that processes each object node in one go and then purges it

This program demonstrates. Note that I have used Data::Dumper only so that you can see the contents of @fields once it has been populated

It is very important that you use strict and use warnings at the top of every Perl program, especially if you are asking for help with it. It is a simple measure that can reveal many straightforward errors that you may otherwise waste a lot of time searching for

Note also that the "indirect object" form of method calls is discouraged: you should write XML::Twig->new(...) instead of new XML::Twig (...).

And if you use single quotes instead of double quotes then a backslash inside a string doesn't need to be doubled-up unless it is the last character of the string. But Perl is quite happy if you use forward slashes as a path separator, even on Windows

I hope this helps

use strict;
use warnings;

use XML::Twig;
use Data::Dumper;
$Data::Dumper::Useqq = 1;

my $twig= XML::Twig->new( twig_handlers => { object => \&get_Object });

my $lokaal = 'c:\temp\data3.xml';

my @fields;
$twig->parsefile($lokaal);


sub get_Object {

  my ($twig, $object) = @_;

  $fields[0] = $object->findvalue('id');
  $fields[1] = $object->findvalue('name');
  $fields[3] = $object->findvalue('type');
  $fields[8] = $object->findvalue('description');

  print Dumper \@fields;

  my @localcosts = $object->findnodes('localcosts/localcost');

  for my $localcost (@localcosts) {

    my $type        = $localcost->findvalue('type');
    my $name        = $localcost->findvalue('name');
    my $description = $localcost->findvalue('description');

    print "$type, $name, $description\n";
  }

  $twig->purge;    
}

output

$VAR1 = [
          "VW-XJC9",
          "Name",
          undef,
          "House",
          undef,
          undef,
          undef,
          undef,
          "<p>some descrioption of the house</p> "
        ];
mandatory, What kind of cost, Some text again, different than the first tag
mirod

As Borodin said, if you have handlers on name, type and description, and you call $twig->purge at the end of each handler, then the elements are removed from the tree. You could set a handler on object, that only does a $twig->purge call, and you would be OK.

You don't need to call purge "too often", just make sure you call it at a low enough level so you don't use too much memory. There is no point really in calling it for each single leaf element.

That's a common mistake, one that I make myself quite often ;--(.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!