-1

I was running a Perl script and I encountered the following result, instead of the answer I expected.

input HASH(0x17268bb0)
input HASH(0x172b3300)
input HASH(0x172b32a0)

Can anyone say what this is and how to rectify it?

This is my XML file here

<Root>
     <Top name="ri_32">
     <Module name="ALU">
        <input name="power_control_bus"/>
        <bidirection name="address_bus"/>
     </Module>
     <Module name="Power_control">
        <input name="cpu_control_bus"/>
        <output name="power_control_bus"/>
        <bidirection name="address_bus"/>
     </Module>
     <input name="address"/>
     <input name="clock"/>
     <input name="data_in"/>
     <output name="data_out"/>
     <bidirection name="control"/>
    </Top>
</Root>

I'm writing a Perl script which can be converted into a specific requirement (.v, .sv file)

use strict;

use XML::Simple;

use Data::Dumper;

my $xml_root = XMLin( './simodule.xml' );
my $root_top = $xml_root->{Top};
my $mod      = $root_top->{Module};

print "Top $root_top->{name}\n";

my $top_in = $root_top->{input};
foreach my $namein ( keys %$top_in ) {
    print " input $top_in->{$namein}\n";
}

my $top_ou = $root_top->{output};
foreach my $nameou ( keys %$top_ou ) {
    print " output $top_ou->{$nameou}\n";
}

my $top_bi = $root_top->{bidirection};
foreach my $namebi ( keys %$top_bi ) {
    print " bidirection $top_bi->{$namebi}\n";
}

output:

Top risc_32
input HASH(0x172b3300)
input HASH(0x172b32a0)
input HASH(0x17268bb0)
output data_out
bidirection control

Expected output

 input address
 input clock
 input data_in
 output data_out
 bidirection control
Divox
  • 101
  • 6

3 Answers3

4

You've made your task more difficult for yourself by using one of the most deceitful modules on CPAN. XML::Simple isn't simple.

But it's docs also suggest not using it: Why is XML::Simple "Discouraged"?

So - how about instead, XML::Twig:

#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;

#$twig now contains our XML data structure. 
my $twig = XML::Twig->new->parsefile('simodule.xml'); 

#fetch a value with an xpath expression - ./Top
#then extract the attribute 'name' from this node. 
print "Top ", $twig->get_xpath( './Top', 0 )->att('name'), "\n";
#iterate all 'input' elements beneath "Top":
#note - single argument to "get_xpath" means all of them in a list. 
foreach my $input ( $twig->get_xpath('./Top/input') ) {
    #retrieve from each their name attribute (and print) 
    print "input ", $input->att('name'), "\n";
}

#locate the 'output' and 'bidirection' nodes within the tree, and fetch
#their name attribute. 
print "output ", $twig -> get_xpath( './Top/output',0) -> att('name'),"\n";
print "bidirection ", $twig -> get_xpath( './Top/bidirection',0) -> att('name'),"\n";

We use XML::Twig which makes use of get_xpath to specify an XML path. We also use att to retrieve a named attribute. You could use iterators such as first_child and children if you prefer though:

#Top element is below the root - we create a reference to it $top
my $top = $twig->root->first_child('Top');
#From this reference, fetch the name attribute. 
print "Top ", $top->att('name'), "\n";
#get children of Top matching 'input' and iterate
foreach my $input ( $top -> children('input') ) {
    #print attribute called 'name'. 
    print "input ", $input->att('name'), "\n";
}
#Find a child below Top called 'output' and retrieve 'name' attribute. 
print "output ", $top -> first_child('output') -> att('name'),"\n";
#as above. 
print "bidirection ", $top -> first_child('bidirection') -> att('name'),"\n";

These are doing the same thing - personally I like xpath as a way of navigating XML but that's a matter of taste. (It lets you do all sorts of things like specify a path with embedded attributes, that kind of thing - moot point in this example though).

Given your input XML, both produce:

Top ri_32
input address
input clock
input data_in
output data_out
bidirection control

it skips the nested hashes for ALU and Power_Control because your original code appears to.

Community
  • 1
  • 1
Sobrique
  • 52,974
  • 7
  • 60
  • 101
  • Let me install the module first and have a check at it! Thanks! time to go behind the admin now ;) – Divox Dec 21 '15 at 09:49
  • That piece of code has been taken care of! But I have a hard time trying to figure out this piece! Let me give a try! – Divox Dec 21 '15 at 09:55
  • 1
    It looks a bit harder to start off with, but trust me - it'll make your life easier in the long run. Added some extra illustration that I hope will clarify. – Sobrique Dec 21 '15 at 10:00
3

You still haven't been at all clear about exactly what output you want. But I use XML::LibXML for most of my XML processing requirements and I'd write something like this:

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

use XML::LibXML;

my $parser = XML::LibXML->new();
my $doc = $parser->parse_file('simodule.xml');

foreach my $type (qw[input output bidirection]) {
  foreach ($doc->findnodes("/Root/Top/$type")) {
    say $_->nodeName, ' ', $_->getAttribute('name');
  }
}
Dave Cross
  • 68,119
  • 3
  • 51
  • 97
  • I want the inputs "name" attributes to be displayed, and there are three attributes to input , rather it throws me an Hash value. You can find the difference in _output_ and _expected output_ – Divox Dec 21 '15 at 12:32
  • Yes, so this code produces exactly your expected output. – Dave Cross Dec 21 '15 at 13:38
  • 3
    It's worth pointing out that through the magic of [XML::LibXML::AttributeHash](https://metacpan.org/pod/XML::LibXML::AttributeHash) you can simply do `$_->{name}` rather than `$_->getAttribute('name')` - with no other changes to your code. – Grant McLean Dec 21 '15 at 20:14
2

The output is correct. As we don't know what exactly you need, I modify your code to following so maybe you can figure out why you see the HASH and how to de-reference it by yourself, it's pretty simple:

use strict;
use XML::Simple;
use Data::Dumper;
local $/;
my $xml_root = XMLin(<DATA>);
print Dumper $xml_root;
my $root_top=$xml_root->{Top};
my $mod=$root_top->{Module};
print "Top $root_top->{name}\n";

my $top_in=$root_top->{input};
foreach my $namein (keys %$top_in)
   {
    print " input" , Dumper $top_in->{$namein};
   }
my $top_ou=$root_top->{output};
foreach my $nameou (keys %$top_ou)
  {
   print " output $top_ou->{$nameou}\n";
  }
my $top_bi=$root_top->{bidirection};
foreach my $namebi (keys %$top_bi)
  {
   print " bidirection $top_bi->{$namebi}\n";
  }

__DATA__
    <Root>
     <Top name="ri_32">
     <Module name="ALU">
        <input name="power_control_bus"/>
        <bidirection name="address_bus"/>
     </Module>
     <Module name="Power_control">
        <input name="cpu_control_bus"/>
        <output name="power_control_bus"/>
        <bidirection name="address_bus"/>
     </Module>
     <input name="address">X</input>
     <input name="clock"/>
     <input name="data_in"/>
     <output name="data_out"/>
     <bidirection name="control"/>
    </Top>
  </Root>
Boying
  • 1,404
  • 13
  • 20
  • Instead of input HASH(0x172b3300), input HASH(0x172b32a0), input HASH(0x17268bb0), I should be actually getting input address, input clock, input data_in as mentioned in the XML file! – Divox Dec 21 '15 at 09:25
  • but there is no actually value in address clock and or data_in, they are empty hashes, have you seen the Dumper code i modified, and I also modifyed your XML to add a "X" in addess, so you can get it in hash, try my code first! – Boying Dec 21 '15 at 09:31
  • even the **bidirection name, output name** has no values and they are empty hashes as well (AFIK) . I'm actually trying to avoid the _Dumper code_ as it is not required – Divox Dec 21 '15 at 09:36
  • if I'm not wrong, will it be feasible to store them in an array(_input_ only because there are three tags). – Divox Dec 21 '15 at 09:40
  • Do you need the name attribute? { print " input" , $namein, Dumper $top_in->{$namein}; } The Dumper code is just for debug. If you know how the hash looks like, you can take the value by accessing the key,unless it's an empty hash – Boying Dec 21 '15 at 09:42
  • the Dumper is returning empty actually! totally clueless now! – Divox Dec 21 '15 at 09:48
  • `input $top_in->{$namein}\n` , what is wrong in this snippet(I'd be interested to know the reason) ?. when `" output $top_ou->{$nameou}\n"` gives you the attribute value why not the former ? – Divox Dec 21 '15 at 09:54
  • I see... because there are only one output item in XML, the module handles it in this way, to prove this, you can do a make a copy of and it will be the same as input. To avoid this ,you can use ForceArray => 1,(see document of XML::Simple) – Boying Dec 21 '15 at 09:58
  • that's correct! Replacing input with output returned the same thing! That's why it confusing! – Divox Dec 21 '15 at 10:01
  • 1
    Welcome to the joy of `XML::Simple`. If you want it to behave consistently you need to set `ForceArray => 1, KeyAttr => [], ForceContent => 1`. Of course, if you do, you'll find each layer is an array of hashes. But at least it'll do so in a consistent fashion. – Sobrique Dec 21 '15 at 11:58