What difference does curly brace make in accessing an object - perl

Not even sure if I used the right terminology..
This was the passed data.
$bug = bless({
'bug_id' => '25252',
'flag_types' => [
bless({
'name' => 'name1',
'flags' => [bless({
'id' => 488052,
}, 'Bugzilla::Flag')],
}, 'Bugzilla::FlagType'),
bless({
'name' => 'name2',
'flags' => [bless({
'id' => 488053,
}, 'Bugzilla::Flag')],
}, 'Bugzilla::FlagType'),
],
}, 'Bugzilla::Bug');
Why can I reference name with or without curly braces, but not the flags?
$_->flags gives error
Can't locate object method "flags"
my #isCrash = map {
print Dumper($_->name);
print Dumper($_->{name});
print Dumper($_->flags); # errors
print Dumper($_->{flags};
} #{ $bug->{flag_types} };
I get that flags is not a method, but why is it that I don't get such an error for name?

Your array contains objects of type Bugzilla::FlagType, they have a method name that "Returns the name of the flagtype".

Related

Why do I get a syntax error when I try to print a nested hash that has keys containing colons?

I'm trying to print an element of a nested data structure:
$VAR1 = {
'SOAP:Body' => {
'ns1:MT_DF_AssetMaster_Response' => {
'SUBNUMBER' => {},
'ASSETCREATED' => {
'SUBNUMBER' => {},
'ASSET' => {},
'COMPANYCODE' => {}
},
'RETURN' => {
'PARAMETER' => 'timedependentdata',
'MESSAGE_V2' => {},
'ID' => 'BAPI1022',
'MESSAGE_V1' => 'HW5790',
'ROW' => '0',
'TYPE' => 'E',
'FIELD' => 'plate_no',
'LOG_NO' => {},
'MESSAGE_V3' => {},
'SYSTEM' => 'xxx',
'MESSAGE' => 'Invalid date transferred for field xxx:',
'MESSAGE_V4' => {},
'NUMBER' => '041',
'LOG_MSG_NO' => '000000'
},
'xmlns:ns1' => 'urn:ariba.com:xi:OnDemand:Asset',
'ASSET' => {},
'COMPANYCODE' => {}
}
},
'xmlns:SOAP' => 'http://schemas.xmlsoap.org/soap/envelope/',
'SOAP:Header' => {}
};
print "$data->{SOAP:Body}->{ns1:MT_DF_AssetMaster_Response}->{ASSETCREATED}=>{ASSET}\n";
But I get a syntax error:
syntax error at ./asset_creation.pl line 85, near "{SOAP:"
How can I fix this?
You must write something like this
my $asset = $data->{'SOAP:Body'}{'ns1:MT_DF_AssetMaster_Response'}{ASSETCREATED}{ASSET};
print %$asset ? "Asset is NOT empty\n" : "Asset is empty\n";
The following are the syntaxes for a hash lookup via reference:
REF->{IDENTIFIER}
REF->{EXPR}
ns1:MT_DF_AssetMaster_Response is neither a valid identifier, nor a valid expression. Replace
->{ns1:MT_DF_AssetMaster_Response}
with
->{'ns1:MT_DF_AssetMaster_Response'}
Perl allows an expression inside the subscripts for an array or a hash. For instance, a variable:
$array[ $i ]
Or the result of an addition:
$array[ $i + $offset ]
Or something
$array[ cos( $i ) ]
It's the same with a hash:
$hash{ $key }
The dot is still the string concatenation operator:
$hash{ $key . $prefix }
It's harder to spot when you have barewords smooshed together:
$hash{first.last}
And in this case, the : is still part of the namespace separator. Perl thinks you aren't done with this expression in the braces so it complains:
$hash{ SOAP:Body } # !!! Error
SOAP:Body must be quoted: The : may not be used without quoting as hash key:
print $data->{'SOAP:Body'}->{'ns1:MT_DF_AssetMaster_Response'}
You should also remove the " " around the variable name in your print statement. The hashref-dereferencing doesn't work otherwise. Your output would be something like
HASH(0x123456)->{SOAP:Body}->{ns1:MT_DF_AssetMaster_Response}
...but you may still have another error if line 85 isn't the print command.

not able to loop through a blessed object

I have an array that results in the following variable with blessed objects inside it. How do I iterate through it to get the name of each variable?
$VAR1 = [
bless( {
'name' => 'apple',
'address' => 'kashmir'
}),
bless( {
'name' => 'mango',
'address' => 'chicago'
})
];
$VAR1 = bless( {
'name' => 'grape',
'address' => 'amsterdam'
});
The [...] indicate that $VAR1 is an array reference, which you dereference with #$VAR1. (Replacing VAR1 with the actual name of the variable, of course. Data::Dumper can't see the actual variable names, so it turns them all into VAR1.) Once you've dereferenced, you can treat it like a normal array, looping over it, pushing, shifting, etc.:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.010;
my $VAR1 = [
bless( {
'name' => 'apple',
'address' => 'kashmir'
}),
bless( {
'name' => 'mango',
'address' => 'chicago'
})
];
for my $item (#$VAR1) {
say $item->{name};
}
Output:
apple
mango

Hash not passing properly between functions

I set up a user hash in a function with the following,
push #{$profile{$index}{$infoName}}, $information
and print it using print Dumper(\%profile); index++; in the function it was set up it prints each of indexes
`$VAR1 = { '374' => { 'degree' => [ 'CS' ], 'birthdate' => [ '1973/12/13' ], 'gender' => [ 'M' ],...}
$VAR1 = { '375' => { 'degree' => [ 'CS' ], 'birthdate' => [ '1933/02/03' ], 'gender' => [ 'F' ],...}`
when i try to access this within another function's foreach loop using print "${$profile{$currIndex}{'gender'}}"; i get odd behaviour where the print returns an empty string and get some random numbers appear in the hash: '$VAR1 = { '4' => {}, '1' => {}, '3' => {}, '2' => {}, '378' => { 'birthdate' => [ '1961/03/29' ], 'gender' => ['F'],..}
How can i properly access the gender feild from within a loop?
push #{$profile{$index}{$infoName}}, $information;
print "${$profile{$currIndex}{'gender'}}";
I'm not even sure what the second line actually does. On my Ubuntu, perl produces an error: not a scalar reference.
What you want is, to print all array elements:
print "#{$profile{$currIndex}{'gender'}}\n";
or, to print the first:
print $profile{$currIndex}->{'gender'}->[0], "\n";
The leaf element is an array references and has to be dereferenced as such.
I'm not sure why you use there array references. In your sample data there are no multiple elements in the arrays. Probably you wanted to write simply this? -
$profile{$index}{$infoName} = $information;
...
print "$profile{$currIndex}{'gender'}\n";

Iterating over bless objects in Perl

I'm working on some code to query F5 load balancers using the BigIP::iControl module.
Right now, I'm getting the following output when doing a Dumper on a variable I get back from a particular function.
I've having a lot of trouble iterating of this object.
How could I go about iterating over this and only taking out the monitor_status for each member?
$VAR1 = [
bless( [
bless( {
'monitor_status' => 'MONITOR_STATUS_UP',
'member' => bless( {
'address' => '127.0.0.0.1',
'port' => '8085'
}, 'Common::IPPortDefinition' )
}, 'LocalLB::PoolMember::MemberMonitorStatus' ),
bless( {
'monitor_status' => 'MONITOR_STATUS_UP',
'member' => bless( {
'address' => '127.0.0.0.1',
'port' => '8085'
}, 'Common::IPPortDefinition' )
}, 'LocalLB::PoolMember::MemberMonitorStatus' ),
bless( {
'monitor_status' => 'MONITOR_STATUS_DOWN',
'member' => bless( {
'address' => '127.0.0.0.1',
'port' => '8085'
}, 'Common::IPPortDefinition' )
}, 'LocalLB::PoolMember::MemberMonitorStatus' ),
bless( {
'monitor_status' => 'MONITOR_STATUS_DOWN',
'member' => bless( {
'address' => '127.0.0.0.1',
'port' => '8085'
}, 'Common::IPPortDefinition' )
}, 'LocalLB::PoolMember::MemberMonitorStatus' )
], 'LocalLB::PoolMember::MemberMonitorStatus[]' )
];
I'm not sure whether those member variables are public - I'm not familiar with the modules used - so this might well violate the encapsulation of the LocalLB::PoolMember::MemberMonitorStatus class. You should check before using.
for my $mms ( #{$VAR1->[0]} ) {
warn $mms->{monitor_status};
}
It would be better to check whether the MemberMonitorStatus class provides an accessor, and possibly an iterator for the member monitor status array.
The above was tested simply by pasting your Dumper output into a Perl script with the code of the for loop implemented based on eyeballing the data structure.
(edit: based on F5 webcentral docs in the Google cache, it may be that MemberMonitorStatus is a simple struct in the underlying code, exposed in the Perl as a class with two member variables - but no behaviour. If so, the above is probably OK.)

How do I access values in the data structure returned by XML::Simple?

Hi everyone,
This is very simple for perl programmers but not beginners like me,
I have one xml file and I processed using XML::Simple like this
my $file="service.xml";
my $xml = new XML::Simple;
my $data = $xml->XMLin("$file", ForceArray => ['Service','SystemReaction',
'Customers', 'Suppliers','SW','HW'],);
Dumping out $data, it looks like this:
$data = {
'Service' => [{
'Suppliers' => [{
'SW' => [
{'Path' => '/work/service.xml', 'Service' => 'b7a'},
{'Path' => '/work/service1.xml', 'Service' => 'b7b'},
{'Path' => '/work/service2.xml', 'Service' => 'b5'}]}
],
'Id' => 'SKRM',
'Customers' =>
[{'SW' => [{'Path' => '/work/service.xml', 'Service' => 'ASOC'}]}],
'Des' => 'Control the current through the pipe',
'Name' => ' Control unit'
},
{
'Suppliers' => [{
'HW' => [{
'Type' => 'W',
'Path' => '/work/hardware.xml',
'Nr' => '18',
'Service' => '1'
},
{
'Type' => 'B',
'Path' => '/work/hardware.xml',
'Nr' => '7',
'Service' => '1'
},
{
'Type' => 'k',
'Path' => '/work/hardware.xml',
'Nr' => '1',
'Service' => '1'
}]}
],
'Id' => 'ADTM',
'Customers' =>
[{'SW' => [{'Path' => '/work/service.xml', 'Service' => 'SDCR'}]}],
'Des' => 'It delivers actual motor speed',
'Name' => ' Motor Drivers and Diognostics'
},
# etc.
],
'Systemreaction' => [
# etc.
],
};
How to access each elements in the service and systemReaction(not provided). because I am using "$data" in further processing. So I need to access each Id,customers, suppliers values in each service. How to get particular value from service to do some process with that value.for example I need to get all Id values form service and create nodes for each id values.
To get Type and Nr value I tried like this
foreach my $service (#{ $data->{Service}[1]{Suppliers}[0]{HW}[0] }) {
say $service->{Nr};
}
foreach my $service (#{ $data->{Service}[1]{Suppliers}[0]{HW}[0] }) {
say $service->{Type};
}
can you help me how to get all Nr and Type values from Supplier->HW.
I suggest reading perldocs Reference Tutorial and References and Nested Data Structures. They contain an introduction and full explanation of how to access data like that.
But, for example, you can access the service ID by doing:
say $data->{Service}[0]{Id} # prints SKRM
You could go through all the services, printing their ID, with a loop:
foreach my $service (#{ $data->{Service} }) {
say $service->{Id};
}
In response to your edit
$data->{Service}[1]{Suppliers}[0]{HW}[0] is an hash reference (you can check this quickly by either using Data::Dumper or Data::Dump on it, or just the ref function). In particular, it is { Nr => 18, Path => "/work/hardware.xml", Service => 1, Type => "W" }
In other words, you've almost got it—you just went one level too deep. It should be:
foreach my $service (#{ $data->{Service}[1]{Suppliers}[0]{HW} }) {
say $service->{Nr};
}
Note the lack of the final [0] that you had.