S
Steve
I have a question about how to generate a multi-level (nested) list
structure by perl. I currently have a 2-level
<ul><li><ul><li></li></ul></li></ul> structure produced via a perl script,
which works fine for its purpose. An example HTML output by the existing
script is:
<ul>
<li><a href=subject_1.0.html>Subject 1.0</a>
<ul>
<li><a href=page_1.1.html>Page 1.1</a></li>
<li><a href=page_1.2.html>Page 1.2</a></li>
<li><a href=page_1.3.html>Page 1.3</a></li>
</ul>
</li>
</ul>
There's more non-relevant code that I've stripped for a bit of clarity,
such as CSS etc. In fact, the actual HTML code is largely irrelavant.
Anyway, a barebone version of the perl procedure generating the above is:
#!/usr/bin/perl -w
use Tie::IxHash;
use strict;
use warnings;
my $object1 = tie my %listoflinks, "Tie::IxHash";
%listoflinks = ('subject_1.0.html', => 'Subject 1.0',
'page1.1.html', => 'Page 1.1',
'page1.2.html', => 'Page 1.2',
'page1.3.html', => 'Page 1.3');
for (\%listoflinks) {
my $firstkey = each %$_;
print "<ul>\n"; # open 1st UL
print "<li><a href=$firstkey>$listoflinks{$firstkey}</a>\n"; # open 1st LI
print "<ul>\n"; # open nested UL
while ( local $_ = each %$_ ) {
{ print "<li><a href=$_>$listoflinks{$_}</a></li> \n" } # print some LI's
}
print "</ul>\n"; # close nested UL
print "</li>\n"; # close first LI
print "</ul>\n"; # close first UL
}
The above procedure was put together with good help from this group ages
ago. As mentioned, the code takes care of the 2-level list structure and
does so by fetching the $firstkey from the array entries or LoH and
inserting the needed opening and closing UL's and LI's in the right places.
However, I'm not quite sure how to change the script to generate a third
level, such as:
<ul>
<li><a href=subject_1.0.html>Subject 1.0</a>
<ul>
<li><a href=page_1.1.html>Page 1.1</a></li>
<li><a href=page_1.2.html>Page 1.2</a></li>
<li><a href=page_1.3.html>Page 1.3</a></li>
<li><a href=subject_2.0.html>Subject 2.0</a>
<ul>
<li><a href=page_2.1.html>Page 2.1</a></li>
<li><a href=page_2.1.html>Page 2.2</a></li>
</ul>
</li>
</ul>
</li>
</ul>
Or for example, the same structure, with another two second-level list
items at the end:
<ul>
<li><a href=subject_1.0.html>Subject 1.0</a>
<ul>
<li><a href=page_1.1.html>Page 1.1</a></li>
<li><a href=page_1.2.html>Page 1.2</a></li>
<li><a href=page_1.3.html>Page 1.3</a></li>
<li><a href=subject_2.0.html>Subject 2.0</a>
<ul>
<li><a href=page_2.1.html>Page 2.1</a></li>
<li><a href=page_2.1.html>Page 2.2</a></li>
</ul>
</li>
<li><a href=page_1.4.html>Page 1.4</a></li>
<li><a href=page_1.5.html>Page 1.5</a></li>
</ul>
</li>
</ul>
Naturally a different array structure would be required in my %listoflinks
to output the above. Any advise or examples how this may be pieced together
would be most helpful.
Perhaps someone has a procedure in use that does something similar already?
Many thanks,
Tuxedo
NB: System load efficiency is not an issue, as the procedure will run only
occasionally on a local machine to generate HTML sent onto a web server in
static format. In other words, the script will not run against any real web
page requests. The procedure is simply meant to be an easy maintenance tool.
I use recursive routines a *lot* in printing out nested data structures,
and they are your friend in cases like this...
The below is:
1) not tested in any way,
2) may not even compile,
3) and is just a concept.
%hash = ( whatever, too lazy to make one );
recurse_hash( \%hash );
sub recurse_hash {
my $refhash = shift;
$refhash or return '';
print "<ul>\n";
while( keys %{$refhash} ){
if( ref $refhash->{$_} eq 'HASH' ){
recurse_hash( $refhash->{$_} );
}
else{
print "<li>$refhash->{$_}</li>\n";
}
}
print "</ul>\n";
}
The beauty of a recursive is it flat doesn't matter how many levels deep
the data structure is.
The downside is it flat doesn't matter how many levels deep the
recursive 'thinks' the data structure is and sloppy programming can
bite you big time..... infinite recursion anyone?
hth,
\s