Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Multi-level list generation

Reply
Thread Tools

Multi-level list generation

 
 
Steve
Guest
Posts: n/a
 
      08-21-2010
On 08/21/2010 02:04 PM, Tuxedo wrote:
> 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


 
Reply With Quote
 
 
 
 
Tuxedo
Guest
Posts: n/a
 
      08-21-2010
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.


 
Reply With Quote
 
 
 
 
Steve
Guest
Posts: n/a
 
      08-21-2010
On 08/21/2010 03:32 PM, Tuxedo wrote:
> Steve wrote:
>
>> On 08/21/2010 02:04 PM, Tuxedo wrote:
>>> 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
>>
>>

>
> Thanks for the above solution! However, it is a bit difficult for me to
> figure exactly how the %hash = (part may be composed) to generate a
> multi-level list structure. Any additional pointers anyone?
>
> Tuxedo
>
>
>


Well.....

my %hash = (
key1 => { subkey => 'value',
subhash => {
subsubkey1 => 'value',
subsubkey2 => 'another value',
},
},
key2 => 'value',
etc => {
},

);

But, 'more better' would be to go a reliable (and vetted) source like:

http://perldoc.perl.org/perldsc.html

hth,

\s
 
Reply With Quote
 
Jürgen Exner
Guest
Posts: n/a
 
      08-21-2010
Tuxedo <> wrote:
>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:

[...]

>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:


If you keep adding additional levels then recursion is your friend:
(sketch in pseudo-code, transfer into actual Perl is left as an
excercise):

sub print_elem {
#arguments: single argument, either reference to list or single item
if (ref $_[0]) { # this element is a reference to a nested list
print_header(); #print header for the sub-list
for (@_) {
print_elem(@{$_}); #print each element of the sub-list
}
print_footer(); #print footer for the sub-list

} else { #this element is a single item
print_item($_[0]; #just print it
}
)


jue
 
Reply With Quote
 
Tuxedo
Guest
Posts: n/a
 
      08-21-2010
Steve wrote:

> On 08/21/2010 02:04 PM, Tuxedo wrote:
> > 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
>
>


Thanks for the above solution! However, it is a bit difficult for me to
figure exactly how the %hash = (part may be composed) to generate a
multi-level list structure. Any additional pointers anyone?

Tuxedo



 
Reply With Quote
 
Tuxedo
Guest
Posts: n/a
 
      08-21-2010
Jürgen Exner wrote:

> Tuxedo <> wrote:
> >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:

> [...]
>
> >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:

>
> If you keep adding additional levels then recursion is your friend:
> (sketch in pseudo-code, transfer into actual Perl is left as an
> excercise):
>
> sub print_elem {
> #arguments: single argument, either reference to list or single item
> if (ref $_[0]) { # this element is a reference to a nested list
> print_header(); #print header for the sub-list
> for (@_) {
> print_elem(@{$_}); #print each element of the sub-list
> }
> print_footer(); #print footer for the sub-list
>
> } else { #this element is a single item
> print_item($_[0]; #just print it
> }
> )
>
>
> jue


This looks like a good solution. Yet difficult for me to translate into
functioning code against an array of hash values or items.

Any bit of clearer description would be greatly appreciated.

Thanks,
Tuxedo


 
Reply With Quote
 
ccc31807
Guest
Posts: n/a
 
      08-21-2010
On Aug 21, 3:04*pm, Tuxedo <tux...@mailinator.com> wrote:
> 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:


Mark Jason Dominus, in 'Higher Order Perl' has a section on parsing
HTML in chapter 1. You can download the book over the internet, but
it's well worth buying, and I would encourage you to do so.

CC
 
Reply With Quote
 
Uri Guttman
Guest
Posts: n/a
 
      08-22-2010
>>>>> "c" == ccc31807 <> writes:

c> On Aug 21, 3:04*pm, Tuxedo <tux...@mailinator.com> wrote:
>> 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:


c> Mark Jason Dominus, in 'Higher Order Perl' has a section on parsing
c> HTML in chapter 1. You can download the book over the internet, but
c> it's well worth buying, and I would encourage you to do so.

the OP isn't parsing but generating html. parsing it should be done with
a module. generating it is done well with templates but he still needs
to learn data structures to work with them. regardless of the
technology, nested html needs nested data which means perl data
structures. they are used in some many perl programs that they are
critical to learn early one. perlreftut, perldsc and perllol are
required reading from the perl docs.

uri

--
Uri Guttman ------ -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
 
Reply With Quote
 
Tuxedo
Guest
Posts: n/a
 
      08-22-2010
Steve wrote:

> On 08/21/2010 03:32 PM, Tuxedo wrote:
> > Steve wrote:
> >
> >> On 08/21/2010 02:04 PM, Tuxedo wrote:
> >>> 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
> >>
> >>

> >
> > Thanks for the above solution! However, it is a bit difficult for me to
> > figure exactly how the %hash = (part may be composed) to generate a
> > multi-level list structure. Any additional pointers anyone?
> >
> > Tuxedo
> >
> >
> >

>
> Well.....
>
> my %hash = (
> key1 => { subkey => 'value',
> subhash => {
> subsubkey1 => 'value',
> subsubkey2 => 'another value',
> },
> },
> key2 => 'value',
> etc => {
> },
>
> );
>
> But, 'more better' would be to go a reliable (and vetted) source like:
>
> http://perldoc.perl.org/perldsc.html
>
> hth,
>
> \s



Thanks for the hash example and perldoc resource. However, it's still a bit
confusing. To gain a bit further understanding I tried to run your script
'as is' but it failed to compile, as of course you warned me it may do. In
saving your script as a file named testrun.pl and running it, the following
errors are repeatedly returned to the shell until I hit Ctrl+C:

<li></li>
Use of uninitialized value in hash element at ./testrun.pl line 27.
Use of uninitialized value in hash element at ./testrun.pl line 31.
Use of uninitialized value in concatenation (.) or string at ./testrun.pl
line 31.
<li></li>
Use of uninitialized value in hash element at ./testrun.pl line 27.
Use of uninitialized value in hash element at ./testrun.pl line 31.
Use of uninitialized value in concatenation (.) or string at ./testrun.pl
line 31.
<li></li>

etc.

Unfortunately I do not understand the meaning of the above errors and if I
redirect the output to a file, like in ./testrun.pl > file.txt, the file
contains a long list of empty <li></li> containers after an opening <ul>:

<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>

etc...

Below is the exact copy of what I tried to run:

#!/usr/bin/perl -w

use strict;
use warnings;

my %hash = (
key1 => { subkey => 'value',
subhash => {
subsubkey1 => 'value',
subsubkey2 => 'another value',
},
},
key2 => 'value',

);


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";
}

Anyone knows where the error(s) in the above procedure are?

Thanks again,
Tuxedo



 
Reply With Quote
 
Tuxedo
Guest
Posts: n/a
 
      08-22-2010
ccc31807 wrote:

> On Aug 21, 3:04*pm, Tuxedo <tux...@mailinator.com> wrote:
> > 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:

>
> Mark Jason Dominus, in 'Higher Order Perl' has a section on parsing
> HTML in chapter 1. You can download the book over the internet, but
> it's well worth buying, and I would encourage you to do so.
>
> CC


Thanks for the tip. Seems to be a good book!

Tuxedo
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
One-step multiples list generation? Efrat Regev Python 7 01-04-2006 12:13 AM
Module list generation Doug Kearns Python 2 12-05-2004 08:05 AM
IP list generation Stephen Briley Python 2 02-18-2004 04:45 PM
IP list generation Stephen Briley Python 3 02-17-2004 07:38 PM
HTML Generation (Next Generation CGI) John W. Long Ruby 4 11-24-2003 04:24 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57