Can anyone recommend solution to my situation with XML
Sorry for not being clear.
The problem I am trying to convey is that XML::Simple does not allow me direct access to the hash, I must refer to the key in question through the XML::Simple module. Using something like $xml->{key}
.
Here is the code I am using and a copy of th开发者_运维百科e hash output.
The reason this is a problem is because I need to construct a series of loops using the keys of the hash [seen below], and I cannot build a foreach loop with a hash referrence, when I tried it, perl gave me an error.
So what I am looking for is a module or solution to allow me to dump the contents of the XML file to a hash that I declare in my script. I also need the ability to write back out to an XML file.
#!/usr/bin/perl
use strict;
use warnings;
use XML::Simple;
use Data::Dumper;
system ("clear");
my $xml = XML::Simple->new;
# Using the XML::Simple object, read guest_os.xml to a hash
my $xml_file = $xml->XMLin('config.xml',
SearchPath => './config',
SuppressEmpty => 1);
$VAR1 = \{
'esxi01' => {
'password' => 'myspoonistoobig!',
'user' => 'root',
'port' => '22'
},
'esxi02' => {
'password' => 'myspoonistoobig!',
'user' => 'root',
'port' => '22'
},
'Setup' => 'FALSE'
};
For me to access a single key/values in the hash that is created [above] I have to use something like this.
$xml_file->{esxi01}{password}.
Oh yeah I forgot the actual XML file.
<Config>
<esxi01>
<password>password</password>
<port>22</port>
<user>root</user>
</esxi01>
<esxi02>
<password>password</password>
<port>22</port>
<user>root</user>
</esxi02>
<Setup>FALSE</Setup>
</Config>
This is the simplest of the 3 or so I have.
Update:
The first part of the loop works with no problem, the problem happens when I try to use the second part of the loop.
Here is the way my code looks
my $xml = XML::Simple->new;
# Using the XML::Simple object, read guest_os.xml to a hash
my $xml_file = $xml->XMLin('config.xml',
SearchPath => './config',
SuppressEmpty => 1);
foreach my $server (keys %$xml_file) {
foreach my $attribute (keys %{$xml_file->{$server}}) {
print "$attribute\n";
}
}
The output looks like this,
Can't use string ("password") as a HASH ref while "strict refs" in use at foreach_test line 21.
I have tried using quotes in several places to fix the problem but nothing seems to work.
I'm not sure if I understand what you need correctly - the question is very confusing. What you SEEM to be asking is:
You have a complicated nested XML. E.g.
<t1><t2><t3>value</t3></t2></t1>
You seem to want to access contents of tag
<t3>
but without needing to go through the hash keys in a hash-of-hash-of... data structure that XML::Simple creates to represent the DOM. E.g. you don't want to do$xml->{t1}->{t2}->{t3}
.
If that's the case, your problem is that you are using a DOM parser. A SAX parser (like XML::Twig
) lets you execute events upon parsing specific tags, e.g. t3
no matter where in the sructure that tag is.
If your problem is that you just don't know which tags exist (as keys in the hash),
you can do keys %$xml
or keys %{ $xml->{t1} }
to list them.
UPDATE
To loop using your example:
foreach my $key (keys %$xml) { # $key will be esxi01, etc...
foreach my $attribute (keys %{ $xml->{$key} }) {
"Key: $key; attribute: $attribute; value: $xml->{$key}->{$attribute}\n";
}
print "Port for $key: $xml->{$key}->{port}\n"; # Hardcoded
}
UPDATE2
The problem is in the <Setup>FALSE</Setup>
XML tag. It has no subtags, so in the hash its value will be a SCALAR and not a hash. To fix, you need to check that the inner element is, indeed, a hash:
foreach my $server (keys %$xml_file) {
next if (ref ($xml_file->{$server}) ne ref({})); # Not a hash
foreach my $attribute (keys %{$xml_file->{$server}}) {
print "$attribute\n";
}
}
You can iterate through the hash using each
or keys
:
while(($key, $value) = each(%$xml)) {
print "key: $key, value: $value\n";
}
foreach my $key (keys %$xml) {
print "key: $key, value: $xml->{$key}\n";
}
精彩评论