Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Reading a Data Hash created via XML::Simple 2

Status
Not open for further replies.

ljsmith91

Programmer
May 28, 2003
305
US
I have an XML file that is thousands of lines long and I need to parse it out. I am attempting to use XML::Simple to read it in and put it into a Hash Array so that I can extract what I need. However, when I go to process with foreach I cant nail down the referenced data elements from the scalars. I have not had to code perl in a long while and I am very rusty and struggling to figure out how to get at the data elements in the hash that it creates for me. I used Data::Dumper (just initial lines printed) and an excerpt from the code pretty close to what the doc says for XML:Simple. Can you help direct me to what I am doing wrong? I know its a weakness in knowing how to use references withing the hash array lists. If I am just trying to get Number of Maple Trees from the {content} container below from Data::Dumper output, how would I get at it? I Have to dig deeper than this into the hash but if I can understand the easier piece then I should be able to get the deeper data. The error that I get on the foreach statement below is that it's "Not a HASH reference ". I have tried many different variations with the same error as result. Thanks in advance for any help/ direction.

use XML::Simple;
my $file = "my.xml";
$configs = XMLin($file);

foreach my $book (@{$configs->{'BOOK:BOOK'}->{'BOOK:Trees'}->{'BOOK:Tree'}->{'BOOK:Maple'}}) {
print "Maple has $book->{content} books \n";
}

(from Data::Dumper)

configs HASH below
$VAR1 = {
'BOOK:BOOK' => {
'BOOK:Trees' => {
'type' => 'Container',
'BOOK:Tree' => [
{
'BOOK:Maple' => {
'content' => '5',
'type' => 'Property'
},
'BOOK:Apple' => {
'content' => '16',
'type' => 'Property'
},
'BOOK:Oak' => {
'content' => '12',
'type' => 'Property'
},
'BOOK:Redwoods' => {
'BOOK:Redwood' => {
'content' => '342',
'type' => 'Property'
},
'type' => 'Category',
'BOOK:Favorites' => {
'BOOK:Favorite' => [
{
'BOOK:Children' => {
'content' => 11',
'type' => 'Property'
},
'BOOK:Adult' => {
'content' => 5',
'type' => 'Property'
},


 
Hi

Neither I do Perl daily, so not able to throw conclusions from what you posted so far. Would have better chance by reproducing the whole problem using a realistic XML file. Could you post a ( syntactically valid ) fragment from your XML, containing all involved nodes ?


Feherke.
feherke.ga
 
Similar to what feherke suggested, why don't you cut your XML file way down so it's just enough for a representative set of data and post the exact Data::Dumper output? It's hard to guess at the exact data structure with information missing.
 
Ok ...I needed to edit it down quite a bit to give a sample. Here is the XML file and another version of Data::Dumper below that which should match up with the XML file. Again, thanks for any help/ direction that you can offer.

XML file:

<?xml version="1.0" ?>
- <BOOK:BOOKConfigurationFiles xmlns:BOOK=" xmlns:FILEMETADATA=" xmlns:CLAR="- <FILEMETADATA:FileMetaData type="Category">
<FILEMETADATA:Report type="Property">Default</FILEMETADATA:Report>
<FILEMETADATA:SmallLayout type="Property">Default</FILEMETADATA:SmallLayout>
</FILEMETADATA:FileMetaData>
- <BOOK:BOOK type="Category">
- <BOOK:Trees type="Container">
- <BOOK:Tree type="Category">
<BOOK:Maple type="Property">2</BOOK:Maple>
<BOOK:Apple type="Property">4</BOOK:Apple>
<BOOK:Oak type="Property">2</BOOK:Oak>
- <BOOK:Favorites type="Container">
- <BOOK:Favorite type="Category">
<BOOK:Children type="Property">3</BOOK:Children>
<BOOK:Adult type="Property">4</BOOK:Adult>
- <BOOK:publishers type="Container">
- <BOOK:publisher type="Category">
<BOOK:Smith type="Property">3</BOOK:Smith>
<BOOK:Brown type="Property">3</BOOK:Brown>
</BOOK:publisher>
</BOOK:publishers>
</BOOK:Favorite>
</BOOK:Favorites>
</BOOK:Tree>
</BOOK:Trees>
- <BOOK:Fruits type="Container">
- <BOOK:Fruit type="Category">
<BOOK:Orange type="Property">10</BOOK:Orange>
<BOOK:Apple type="Property">5</BOOK:Apple>
<BOOK:Banana type="Property">6</BOOK:Banana>
- <BOOK:Favorites type="Container">
- <BOOK:Favorite type="Category">
<BOOK:Children type="Property">7</BOOK:Children>
<BOOK:Adult type="Property">0</BOOK:Adult>
- <BOOK:publishers type="Container">
- <BOOK:publisher type="Category">
<BOOK:Smith type="Property">2</BOOK:Smith>
<BOOK:Brown type="Property">1</BOOK:Brown>
</BOOK:publisher>
</BOOK:publishers>
</BOOK:Favorite>
</BOOK:Favorites>
</BOOK:Fruit>
</BOOK:Fruits>
</BOOK:BOOK>
</BOOK:BOOKConfigurationFiles>
- <!-- 4444rrrrrrrrrrffffffffffffffff
-->



Data::Dumper

$VAR1 = {
'FILEMETADATA:FileMetaData' => {
'FILEMETADATA:SmallLayout' => {
'content' => 'Default',
'type' => 'Property'
},
'FILEMETADATA:Report' => {
'content' => 'Default',
'type' => 'Property'
},
'type' => 'Category'
},
'BOOK:BOOK' => {
'BOOK:Trees' => {
'BOOK:Tree' => {
'BOOK:Favorites' => {
'BOOK:Favorite' => {
'BOOK:publishers' => {
'type' => 'Container',
'BOOK:publisher' => {
'BOOK:Smith' => {
'content' => '3',
'type' => 'Property'
},
'BOOK:Brown' => {
'content' => '3',
'type' => 'Property'
},
'type' => 'Category'
}
},
'BOOK:Children' => {
'content' => '3',
'type' => 'Property'
},
'BOOK:Adult' => {
'content' => '4',
'type' => 'Property'
},
'type' => 'Category'
},
'type' => 'Container'
},
'BOOK:Apple' => {
'content' => '4',
'type' => 'Property'
},
'BOOK:Maple' => {
'content' => '2',
'type' => 'Property'
},
'type' => 'Category',
'BOOK:Oak' => {
'content' => '2',
'type' => 'Property'
}
},
'type' => 'Container'
}
};
 
Hi

And the desired output is "Maple has 2 books" ? Then removing the [tt]@{[/tt]..[tt]}[/tt] seems enough ( at least with that data ) :
Perl:
[b]foreach[/b] [b]my[/b] [navy]$book[/navy] [teal]([/teal][navy]$configs[/navy][teal]->{[/teal][i][green]'BOOK:BOOK'[/green][/i][teal]}->{[/teal][i][green]'BOOK:Trees'[/green][/i][teal]}->{[/teal][i][green]'BOOK:Tree'[/green][/i][teal]}->{[/teal][i][green]'BOOK:Maple'[/green][/i][teal]})[/teal] [teal]{[/teal]
    [b]print[/b] [i][green]"Maple has $book->{content} books \n"[/green][/i][teal];[/teal]
[teal]}[/teal]
But will there ever be more than one BOOK:Maple tags ? Will BOOK:Maple ever have child tags ?


Feherke.
feherke.ga
 
Thanks feherke.qa !!

That did work...one last question, how would I print the key with it? Example code does not work but you get the isead of what I am trying to do.

foreach my $book ($configs->{'BOOK:BOOK'}->{'BOOK:Trees'}->{'BOOK:Tree'}) {
print "$book has $book->{content} books \n";
}

Would produce each Key woth content.

or "BOOK:Maple has 2 books"
"BOOK:Apple has 4 books"
"BOOK:Oak has 2 books"

Thanks for the help.
 
It's usually a good idea to get in the habit of using warnings and strict pragmas. With that in mind, this should do what you're looking for:
Code:
foreach my $book (sort keys %{$configs->{'BOOK:BOOK'}{'BOOK:Trees'}{'BOOK:Tree'}}) {
	if ($book =~ m/^\s*BOOK/) {
		next if $book =~ /favorite/i;	# Skip the Favorites branch
		print "$book has $configs->{'BOOK:BOOK'}{'BOOK:Trees'}{'BOOK:Tree'}{$book}{content} books\n";
	}
}
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top