tpais has asked for the wisdom of the Perl Monks concerning the following question:

Hi everybody,

I try to catch vhost data (multiple files) from Apache with the Module Apache::ConfigFile. This works so far.

But after that, I want to write the Hash of Hashes of (Hashes/Arrays) ... into XML file.

How may I iterate perfectly over unknown Hash of Hashes of Hashes or Arrays of ...

What I do not want: foreach () { foreach () { foreach () { ...

May you help me ?

Replies are listed 'Best First'.
Re: Apache::ConfigFile iterate problem
by moritz (Cardinal) on Sep 06, 2010 at 17:54 UTC
    Usually you define a recursive function that accepts a hash, an array or a scalar, and does something with the scalars and calls itself for each item of the array or hash.

    But in the end it depends on what you want to do with the data.

    Perl 6 - links to (nearly) everything that is Perl 6.
Re: Apache::ConfigFile iterate problem
by dasgar (Priest) on Sep 06, 2010 at 18:29 UTC

    Here's my understanding of what your situation. First, you have a complex data structure ("Hash of Hashes of (Hashes/Arrays)"). Second, you want to put this complex data structure into an XML file. Is that correct?

    Assuming that my description above is correct, one method would be to use XML::Simple to generate the XML for you. The code for doing that would be something like this:

    use strict; use XML::Simple; my $data; # insert code to create complex data structure in $data; my $xml = XMLout($data, XMLDecl => 1); open(FH,">output.xml") || die "Unable to open 'output.xml': $!\n"; print FH $xml; close FH;

    If you don't care for XML::Simple, there are other modules that might be able to do something similar. I mentioned this module because I've used it and it sounded like you already had a data structure that could be used as is by this module.

      Thank you for your code. This works wonderful for an singular vhost.

      (XML::Simple make an stop after one vhost. I don't know why.)

      I have multiple vhosts in multiple files and now I have a code which can become analyzed:

      foreach for $xml and open/close does not work well.

      use Apache::ConfigFile; foreach my $vh_file (@vhost_files) { next if $vh_file =~ /000.*/; my $ac = Apache::ConfigFile->read(file=>"$vhost_path/$vh_file", ig +nore_case=>0, fix_booleans=>0); my @vhkeys = $ac->cmd_context('VirtualHost'); for my $vhkey (@vhkeys) { foreach my $vhost ( $ac->cmd_context(VirtualHost => $vhkey) ) { my $sn=$vhost->cmd_config('ServerName'); $vh{$sn} = $vhost->data; } } } my $xml = XMLout(\%vh, XMLDecl => 1); open(FH,">>/tmp/output1.xml") || die "Unable to open 'output.xml': + $!\n"; print FH $xml; close FH;
Re: Apache::ConfigFile iterate problem
by roboticus (Chancellor) on Sep 06, 2010 at 18:30 UTC

    Another hint: You may find the ref function useful. That, combined with moritz' suggested recursive function should do the trick.

    ...roboticus

      Hi,

      I have tried that bevore.

      sub iterate_hash { my $ref = shift; foreach (keys %$ref) { if (ref($ref->{$_}) eq "HASH") { iterate_hash($ref->{$ +_}) } if (ref($ref->{$_}) eq "ARRAY" ) { iterate_array($ref- +>{$_})} else { print "$_ maps to $ref->{$_}\n" } } } sub iterate_array { my $ref = shift; foreach (@$ref) { if (ref($_) eq "HASH") { iterate_hash($_) } if (ref($_) eq "ARRAY" ) { iterate_array($_) } else { print "Array: $_\n" } } } &iterate_hash(\%vh);

      It didnt work out for me.

        It's a workable solution as indicated by others. So, if it didn't work for you you might ask where and why it failed, or tell us where if you know and ask why.

        I noticed something curious about your example code, and since you wrote it I'm wondering why you didn't find it curious. You're iterating over one level if it's an array but a different level if it's a hash. Is that really how your data structure looks?

        I'd suggest trying Data::Dumper to see what your data looks like at different points of your program. The processing code needs to process the proper part of the data each time, or you'll get odd results you didn't expect.

        tpais:

        If you provided a bit of test data and a description of what it did wrong, you'd have a pretty good question here.

        What's the difference between what this code does and what you want?

        ...roboticus

Re: Apache::ConfigFile iterate problem
by metaperl (Curate) on Sep 07, 2010 at 18:31 UTC

      Ah, thank you. I will try this one too.