[19885] in Perl-Users-Digest

home help back first fref pref prev next nref lref last post

Perl-Users Digest, Issue: 2080 Volume: 10

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Tue Nov 6 18:10:54 2001

Date: Tue, 6 Nov 2001 15:10:14 -0800 (PST)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)
Message-Id: <1005088213-v10-i2080@ruby.oce.orst.edu>
Content-Type: text

Perl-Users Digest           Tue, 6 Nov 2001     Volume: 10 Number: 2080

Today's topics:
    Re: moving files (Joe Smith)
    Re: Naive Q: Why Java speed >> Perl speed? (Logan Shaw)
    Re: Optomizing Speed for Large Files <goldbb2@earthlink.net>
        SDBM_File source code? (q777)
    Re: SDBM_File source code? (Joe Smith)
    Re: Small '-w' Question with Net::POP3 <newsgroup_mike@ultrafusion.co.uk>
    Re: Small '-w' Question with Net::POP3 <newsgroup_mike@ultrafusion.co.uk>
    Re: Some very basic questions <tintin@snowy.calculus>
    Re: too late for -T? (Miko O'Sullivan)
    Re: too late for -T? (Dave Hoover)
    Re: using a variable in a subroutine name <mjcarman@home.com>
    Re: using a variable in a subroutine name (Mark Jason Dominus)
    Re: using a variable in a subroutine name <uri@stemsystems.com>
        using modules in subdirectories with a dash <lee@sst.ll.mit.edu>
    Re: using modules in subdirectories with a dash (Tad McClellan)
    Re: using modules in subdirectories with a dash (Mark Jason Dominus)
    Re: XML::Records (was Re: XML parsing) <bart.lateur@skynet.be>
        Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)

----------------------------------------------------------------------

Date: Tue, 06 Nov 2001 21:49:11 GMT
From: inwap@best.com (Joe Smith)
Subject: Re: moving files
Message-Id: <rVYF7.3404$Le.82912@sea-read.news.verio.net>

In article <jsKF7.77812$ez.10056973@news1.rdc1.nj.home.com>,
bubba  <pmi@iname.com> wrote:
>I need to write this in perl (part of a larger program)
>
>in Bash shell:    mv `ls | head -50` ../dir
>
>"Move the first 50 files from this directory to another directory

http://www.inwap.com/mybin/?hourly.pl has sample code to do that.
It runs on Unix and on Win9x.
	-Joe

--
See http://www.inwap.com/ for PDP-10 and "ReBoot" pages.


------------------------------

Date: 6 Nov 2001 14:26:04 -0600
From: logan@cs.utexas.edu (Logan Shaw)
Subject: Re: Naive Q: Why Java speed >> Perl speed?
Message-Id: <9s9h0s$62p$1@charity.cs.utexas.edu>

In article <9s7ju3$kqj$3@news.panix.com>, kj0  <kj0@mailcity.com> wrote:
>Why is it that, typically, the Java VM runs programs so much faster
>than the Perl interpreter?  Is it because of Java's strong typing?  Or
>is it some other difference between the languages that accounts for
>this disparity?

I think this sometimes happen because Perl encourages you to work at a
higher level than Java does.  For instance, in Java, you might do
something like this:

	Vector filtered = new Vector(original.length);

	for (int i = 0; i < original.length; i++)
	{
	    if (sometest(original[i]))
	    {
		filtered.add (original[i]);
	    }
	}

In Perl, you'd probably just do this:

	@filtered = grep (sometest($_), @original);

The Perl version is much, much easier to write, but it requires more
work to execute because (assuming I understand correctly) it creates a
temporary list and then assigns that list to the array.  (I'm assuming
perl doesn't optimize this away; it could in the case where you have an
lvalue that's an array.)

The Perl version might be faster if you do an analogous thing:

	foreach my $element (@original)
	{
	    push (@filtered, $element) if sometest($element);
	}

But here, perl is going to have to grow the array several times as it
finds it doesn't have enough room in it.

Now, somebody will probably post a way that's efficient, and that's
great, but it won't change the fact that lots of people won't do it the
efficient way.  So essentially, I guess what I'm saying is that since
Perl is a higher-level language, it is easier to ignore performance
issues.

Here's another example of code where the easiest way to do it in Perl
is slower than the easiest way to do it in Java.  Say you want to have
an object that has a first name, a last name, and a date of birth
stored in it.  In Perl, you'll probably do this:

	package MyObject;

	sub new
	{
	    my $class = shift;
	    my $self = {};
	    bless $self, $class;

	    @self->{firstname, lastname, birthdate} = @_;

	    return $self;
	}

In Java, it'd be more like this:

	public class MyObject
	{
	    String firstname;
	    String lastname;
	    String birthdate;

	    MyObject (String _firstname, String _lastname, String _birthdate)
	    {
		firstname = _firstname.clone();
		lastname = _lastname.clone();
		birthdate = _birthdate.clone();
	    }
	}

Why is this significant?  Because Perl must find something in a hash
every time it needs to find/use a member variable for that object.
With the Java version, the offsets for the member variables can be
computed at compile time.  So Java just has to add an offset.  Perl has
to calculate the hash value of a string, find it in the hash, and then
compare that string to the key in the hash to make sure it's right.
Perl also has to create hashes at run-time when each object is
created.

Also, Java may be faster in some cases because some JVMs have the
ability to translate byte code into machine code.  Perl doesn't do
this.  I hear that perl is pretty efficient at interpreting its byte
code, but it's still not quite the same thing.

On the other hand, Java is not going to be as fast if you're doing
text-manipulation or other things that Perl is heavily optimized for.

  - Logan
-- 
"In order to be prepared to hope in what does not deceive,
 we must first lose hope in everything that deceives."

                                          Georges Bernanos


------------------------------

Date: Tue, 06 Nov 2001 15:48:08 -0500
From: Benjamin Goldberg <goldbb2@earthlink.net>
Subject: Re: Optomizing Speed for Large Files
Message-Id: <3BE84C88.B482B390@earthlink.net>

Doyle Rivers wrote:
> 
> Here is my situation:
> 
> I am crunching an extreme amount of data that populates a mildly
> complicated hash structure which then needs to be printed to a file.
> Said file usually consist of nearly 300k lines with 60-80 characters
> per line.  Needless to say this takes a really long time to print to
> the file from the hash.
> 
> What I am looking for help on is optomizing the the speed at which the
> data is printed to a file.
> 
> Basically my program reads a bunch of really large data files and
> builds a report that tells how many leaves are on each branch of each
> tree in each field at sevearl different times, it also calculates the
> change in the number of leaves on each branch. (Ok this isn't really
> what it does but it's a good analogy)
> 
> The following is the code* I am using to generate the file:
> 
> sub report
> {
>         print "sub report: @_\n" if $debug;
> 
>         my ($reportfile) = $path."report.tmp";
>         my (    $field,
>                 $tree,
>                 $data,
>                 $delta,
>                 $rp,
>                 @delta);

Blech.  Declare your lexicals for the smallest scope you can.
It won't slow your code down, and will improve readability, and may
catch some bugs.

>         &print_header;

Are you sure you want the semantics which & provides?
I would write this line as:

        print_header();

>         foreach $field (keys %data)
>         {

Since you're not sorting it, you can/should replace foreach/keys with
while/each :

        while( my ($field, $trees) = each %data ) {

>             foreach $tree ( sort numerically keys %{ $data{$field} })
>                 {

Passing the name of a sortsub can be slower than having a block,
especially since perl optomizes certain blocks.

            foreach my $tree ( sort { $a <=> $b } keys %$trees ) {

>                         my ($begin) = 0;
>                         @branch = ();
>                         foreach $rp (@rp)

                       foreach my $rp (@rp)

After all, you don't *use* $rp anywhere except in this loop, so you
should have it *declared* only for this loop.

>                         {
>                                 if ($begin == 0)
>                                 {
>                                         $begin = 1;
>                                         print OUT $field;
>                                         print OUT $seperator,$tree;
>                                 }
> 
>                                 print OUT $seperator;
> 
>                                 if (defined($data{$field}{$tree}{$branch}))
>                                 {
>                                         push @leaves, $data{$field}{$tree}{$branch};
>                                         print OUT sprintf "%0.1f", $data{$field}{$tree}{$branch};
>                                 }
> 
>                                 else
>                                 {
>                                         push @leaves, "UD";
>                                 }
>                         }

Where's @rp defined, or $branch?
Using my PSI::ESP module, I will magically divine what you meant.

print OUT $field, $seperator, $tree;
my @newleaves = values %{$trees->{$tree}};
print OUT $seperator, join $seperator,
    map { defined ? sprintf "%0.1f", $_ : "" }, @newleaves;
print OUT "\n";
push @leaves => map { defined ? $_ : "UD" } @newleaves;

> 
>                         @delta = &calc_delta(@branch) if ($#branch > 0);

                       @delta = &calc_delta(@branch) if (@branch > 1);

There's no speed difference, but the intent of what is being compared
is much clearer with @branch than $#branch.

>                         foreach $delta (@delta)
>                         {
>                                 print OUT $seperator;
> 
>                                 if ($delta ne "")
>                                 {
>                                         print OUT sprintf "%0.1f",$delta;
>                                 }
>                         }
>                         print OUT "\n";

print OUT $seperator, join $seperator,
    map { length ? sprintf "%0.1f", $_ : "" }, @delta;
print OUT "\n";

>                 }
>         }
> }
> 
> Notes:
> -The calc_delta function is already optomized.
> -There are a fixed number of branches on each tree
> -floating point numbers are used for $data{$field}{$tree}{$branch} and
> $delta  (I count tenths of leaves too)
> 
> *All variable names have been changed to protect the innocent.

Which is probably why you code doesn't entirely make sense.  If you
posted your real code, rather than changing the names, and if you didn't
omit things like the definition/declaration of @rp it would make more
sense, and we could help you more.

-- 
Klein bottle for rent - inquire within.


------------------------------

Date: 6 Nov 2001 12:17:50 -0800
From: quang777@email.com (q777)
Subject: SDBM_File source code?
Message-Id: <9f14310.0111061217.7ea25eca@posting.google.com>

I'm trying to find the source code for the SDBM_File module so I can
increase the default max block size. Does anyone know where I can find
the source for it to do this?


------------------------------

Date: Tue, 06 Nov 2001 21:30:42 GMT
From: inwap@best.com (Joe Smith)
Subject: Re: SDBM_File source code?
Message-Id: <6EYF7.3400$Le.83160@sea-read.news.verio.net>

In article <9f14310.0111061217.7ea25eca@posting.google.com>,
q777 <quang777@email.com> wrote:
>I'm trying to find the source code for the SDBM_File module so I can
>increase the default max block size. Does anyone know where I can find
>the source for it to do this?

It's included with the perl sources.
  perl5.005_03/ext/SDBM_File/sdbm/README
  perl-5.6.1/ext/SDBM_File/sdbm/README
	-Joe
--
See http://www.inwap.com/ for PDP-10 and "ReBoot" pages.


------------------------------

Date: Tue, 06 Nov 2001 19:46:45 GMT
From: "Mike Mackay [Ultrafusion]" <newsgroup_mike@ultrafusion.co.uk>
Subject: Re: Small '-w' Question with Net::POP3
Message-Id: <F6XF7.1719$3N6.357098@news1.cableinet.net>

Yes that is my real code, in regards to the mailserver not being quoted, I
made a typo while posting the code to the NG and changing the real values.
Sorry I didn't spot that.

Yes, for some reason when I enable to warnings on the shebang line and the
password is incorrect I get an 'Error 500' in the browser. When I remove
the -w switch and enter an incorrect password, it says my custom error
message in the browser.

In regards to the exit statement, I will change my programming practice for
that in the future.


Regars,
Mike Mackay.




------------------------------

Date: Tue, 06 Nov 2001 20:00:28 GMT
From: "Mike Mackay [Ultrafusion]" <newsgroup_mike@ultrafusion.co.uk>
Subject: Re: Small '-w' Question with Net::POP3
Message-Id: <wjXF7.1769$3N6.365560@news1.cableinet.net>

For some reason the 'Error 500' seems to disappear when I load the Carp
module :
use CGI::Carp qw(fatalsToBrowser);

Hmmmmm, oh well. It still enables me to use the -w on the shebang line.....!




------------------------------

Date: Wed, 7 Nov 2001 08:26:26 +1100
From: "Tintin" <tintin@snowy.calculus>
Subject: Re: Some very basic questions
Message-Id: <zyYF7.1$T66.231491@news.interact.net.au>


"Dynamo" <robin1@otenet.gr> wrote in message
news:9s8pcg03dt@enews4.newsguy.com...
> > > Since javascript and HTML can also be written in a text editor, and I
> > > only want to use perl as a tool for my website, what advantages will I
gain
> > > by using perl instead of javascript or HTML.?
> >
> > Perl, Javascript and HTML are three different things.  Javascript is
> > (mostly) a scripting language to run client side in your browser.  HTML
is
> > just a markup language, not a programming language.
> >
>
> OK. Got that I think. If I write javascript and the client hasn't got java
> script enabled then he won't be able to interpret my scripting. By the
same
> comparison if I write a perl script and I don't have perl installed I
cannot
> interpret my own scripting.

That is correct, but if you are talking about using Perl in a web
environment, the client doesn't need Perl installed as the Perl script runs
on the web server and just spits out HTML (mostly).







------------------------------

Date: 6 Nov 2001 12:07:03 -0800
From: miko@idocs.com (Miko O'Sullivan)
Subject: Re: too late for -T?
Message-Id: <db27ea77.0111061207.6af755a7@posting.google.com>

"Nicholas R. Markham" <nickmarkham@mailandnews.com> wrote in message news:<9s8uun$uik$1@newsfeeds.rpi.edu>...
>
> #! /usr/bin/perl -T
> 
> But when I try to run it, perl says 'Too late for "-T" option at script.cgi
> line 1.' How can the first line of the script be too late?

I'm going to take a stab that you're checking that it compiles from
the command line, and that you're doing it something like this:

  perl -c mycgi.pl

or even just 

  perl mycgi.pl

If that's the case, try it like this instead:

  perl -cT mycgi.pl

BTW, your bangpath ought to have warnings, like this:

  #!/usr/bin/perl -Tw

-Miko


------------------------------

Date: 6 Nov 2001 12:27:58 -0800
From: redsquirreldesign@yahoo.com (Dave Hoover)
Subject: Re: too late for -T?
Message-Id: <812589bb.0111061227.3a2b552a@posting.google.com>

Nicholas wrote:
> I have a Perl CGI (several, in fact) that I want to make more secure using
> taint mode.  The shebang line looks like
> 
> #! /usr/bin/perl -T
> 
> But when I try to run it, perl says 'Too late for "-T" option at script.cgi
> line 1.'
> How can the first line of the script be too late?

I have received this error when trying to test a script from the
command line by entering something like:

% perl my_script.cgi

If you have taint mode on, you need to specify that at the command
line like this:

% perl -T my_script.cgi

HTH

--
Dave Hoover
"Twice blessed is help unlooked for." --Tolkien
http://www.redsquirreldesign.com/dave


------------------------------

Date: Tue, 06 Nov 2001 12:48:36 -0600
From: Michael Carman <mjcarman@home.com>
Subject: Re: using a variable in a subroutine name
Message-Id: <3BE83084.ACC43E8D@home.com>

Kristina Clair wrote:
> 
> I'm trying to use a variable in the name of a subroutine, like so:
>
>     foreach my $x ("email_zip", "email_txt", "cp_zip", "cp_txt") {
>         if ($res = _send_$x($domain, $file, $date, $location)) {

Ack! What you're trying to do is use a symbolic reference. Trust me, you
don't really want to do that. Use hard references instead:

    my %send = (
        email_zip => \&_send_email_zip,
        email_txt => \&_send_email_txt,
        cp_zip    => \&_send_cp_zip,
        cp_txt    => \&_send_cp_txt,
    );

    foreach my $x (qw/email_zip email_txt cp_zip cp_txt/) {
        if ($res = $send{$x}->($domain, $file, $date, $location)) {
            # ...
        }
    }

-mjc


------------------------------

Date: Tue, 06 Nov 2001 20:49:15 GMT
From: mjd@plover.com (Mark Jason Dominus)
Subject: Re: using a variable in a subroutine name
Message-Id: <3be84cca.40d4$134@news.op.net>

In article <3BE83084.ACC43E8D@home.com>,
Michael Carman  <mjcarman@home.com> wrote:
>Ack! What you're trying to do is use a symbolic reference. Trust me, you
>don't really want to do that. 

I'm not clear on why not.  So far three people have said "you don't
want to do that" without explaining what the problem might be.

What's the problem?

>    my %send = (
>        email_zip => \&_send_email_zip,
>        email_txt => \&_send_email_txt,
>        cp_zip    => \&_send_cp_zip,
>        cp_txt    => \&_send_cp_txt,
>    );

I think this comes under the heading of what Michael Schwern  likes to
call "Monkey Code".  You have a table with four entries that encodes
essentially no information.  What's the benefit here?

This is a serious question, by the way.
-- 
@P=split//,".URRUU\c8R";@d=split//,"\nrekcah xinU / lreP rehtona tsuJ";sub p{
@p{"r$p","u$p"}=(P,P);pipe"r$p","u$p";++$p;($q*=2)+=$f=!fork;map{$P=$P[$f^ord
($p{$_})&6];$p{$_}=/ ^$P/ix?$P:close$_}keys%p}p;p;p;p;p;map{$p{$_}=~/^[P.]/&&
close$_}%p;wait until$?;map{/^r/&&<$_>}%p;$_=$d[$q];sleep rand(2)if/\S/;print


------------------------------

Date: Tue, 06 Nov 2001 22:21:26 GMT
From: Uri Guttman <uri@stemsystems.com>
Subject: Re: using a variable in a subroutine name
Message-Id: <x74ro7v8ti.fsf@home.sysarch.com>

>>>>> "MJD" == Mark Jason Dominus <mjd@plover.com> writes:

  MJD> In article <3BE83084.ACC43E8D@home.com>,
  MJD> Michael Carman  <mjcarman@home.com> wrote:
  >> Ack! What you're trying to do is use a symbolic reference. Trust me, you
  >> don't really want to do that. 

  MJD> I'm not clear on why not.  So far three people have said "you don't
  MJD> want to do that" without explaining what the problem might be.

  MJD> What's the problem?

  >> my %send = (
  >> email_zip => \&_send_email_zip,
  >> email_txt => \&_send_email_txt,
  >> cp_zip    => \&_send_cp_zip,
  >> cp_txt    => \&_send_cp_txt,
  >> );

  MJD> I think this comes under the heading of what Michael Schwern
  MJD> likes to call "Monkey Code".  You have a table with four entries
  MJD> that encodes essentially no information.  What's the benefit
  MJD> here?

  MJD> This is a serious question, by the way.

you wrote the varvar series of articles. it is the same problem. what if
some random string ws passed in from the outside and a bad sub was
called? at least check the sub name against a hash for verification. and
there is no guarantee that the string name will always be a substring of
the sub name and in the same place in the name. a hash allows freedom to
map different names to subs. using the symbol table is not appropriate
for this as there may be many more possible subs there than you want to
allow. a dispatch table allows this to work under use strict which is a
benefit as well and i believe it will untaint a sub name too.

it doesn't matter that subs are being used here instead of variables,
symrefs can lead to all sorts of hard to fix problems and are
obsfucating at best even when they work

are those enough reasons?

uri

-- 
Uri Guttman  ------  uri@stemsystems.com  -------- http://www.stemsystems.com
-- Stem is an Open Source Network Development Toolkit and Application Suite -
----- Stem and Perl Development, Systems Architecture, Design and Coding ----
Search or Offer Perl Jobs  ----------------------------  http://jobs.perl.org


------------------------------

Date: Tue, 6 Nov 2001 14:08:38 -0500
From: "Lee Rossey" <lee@sst.ll.mit.edu>
Subject: using modules in subdirectories with a dash
Message-Id: <3be83505$0$3940$b45e6eb0@senator-bedfellow.mit.edu>

I'm using perl modules and would like to reference them for use in other
perl programs. The problem is that '-' (dash) doesn't seem to be valid for
directory/filenames. For example to reference the module gbook.pm in the
directory me/exploits/CVE-2000-1131_GCI_Guestbook/gbook.pm we would use:

use me::exploits::CVE-2000-1131_GCI_Guestbook::gbook;

The problem is with the '-' in the CVE name. If we used '_' it's not a
problem.  The parser is interpreting the dash as a minus sign and therefore
creating a compilation error.

Note, there are hundreds of unique directories and it's impractical to put
all the modules in a common @INC path.  Also the 'me' is in the perl include
path.

NOTE: I tried to (1) escape the '-' with \, (2) use "" or ' '  around the
whole statement ... But failed.

PERL version: I tried on 5.6.0 and 5.0

 ... Any suggestions ... Other than changing our whole naming scheme ???

thank you,
-lee






------------------------------

Date: Tue, 06 Nov 2001 19:36:31 GMT
From: tadmc@augustmail.com (Tad McClellan)
Subject: Re: using modules in subdirectories with a dash
Message-Id: <slrn9ugcbb.bsm.tadmc@tadmc26.august.net>

Lee Rossey <lee@sst.ll.mit.edu> wrote:

>The problem is that '-' (dash) doesn't seem to be valid for
>directory/filenames. 


That is not correct.

What is allowed in filenames is determined by the operating system,
not by the programming language.

If hyphens in filesystem names is really your problem, then it
is not a Perl problem.

But I'm guessing that hyphens in filesystem names is NOT your
real problem.


>For example to reference the module gbook.pm in the
>directory me/exploits/CVE-2000-1131_GCI_Guestbook/gbook.pm we would use:
>
>use me::exploits::CVE-2000-1131_GCI_Guestbook::gbook;
>
>The problem is with the '-' in the CVE name. If we used '_' it's not a
>problem.  


   perldoc -f use

says:  "Module I<must> be a bareword"

It is not a bareword if it contains a hyphen.


>The parser is interpreting the dash as a minus sign and therefore
>creating a compilation error.


>... Any suggestions ... Other than changing our whole naming scheme ???


   use lib 'me/exploits/CVE-2000-1131_GCI_Guestbook';  # no bareword
   use gbook;

or some variation thereof.


-- 
    Tad McClellan                          SGML consulting
    tadmc@augustmail.com                   Perl programming
    Fort Worth, Texas


------------------------------

Date: Tue, 06 Nov 2001 20:55:15 GMT
From: mjd@plover.com (Mark Jason Dominus)
Subject: Re: using modules in subdirectories with a dash
Message-Id: <3be84e32.4108$31c@news.op.net>

In article <3be83505$0$3940$b45e6eb0@senator-bedfellow.mit.edu>,
Lee Rossey <lee@sst.ll.mit.edu> wrote:
>use me::exploits::CVE-2000-1131_GCI_Guestbook::gbook;

Try

BEGIN { load_modules('me::exploits::CVE-2000-1131_GCI_Guestbook::gbook',
                     ...);
      }

sub load_modules {
  my @modules = @_;
  for my $mod (@modules) {
    my $file = $mod;
    $file =~ s{::}{/}g;      
    $file .= ".pm";
    require $file && $mod->import();
  }
}


Or some variation of that.
-- 
@P=split//,".URRUU\c8R";@d=split//,"\nrekcah xinU / lreP rehtona tsuJ";sub p{
@p{"r$p","u$p"}=(P,P);pipe"r$p","u$p";++$p;($q*=2)+=$f=!fork;map{$P=$P[$f^ord
($p{$_})&6];$p{$_}=/ ^$P/ix?$P:close$_}keys%p}p;p;p;p;p;map{$p{$_}=~/^[P.]/&&
close$_}%p;wait until$?;map{/^r/&&<$_>}%p;$_=$d[$q];sleep rand(2)if/\S/;print


------------------------------

Date: Tue, 06 Nov 2001 21:51:55 GMT
From: Bart Lateur <bart.lateur@skynet.be>
Subject: Re: XML::Records (was Re: XML parsing)
Message-Id: <s2lgutsm6g4nu3thahc8pms2h2cpe35t80@4ax.com>

Bart Lateur wrote:

>But the gist should be clear: the hash contains both the directly
>accessible individual elements and the ordered tree, side by side,
>without conflict because of the use of (hopefully) illegal characters
>for XML tags, with a high perlish mnemonic value. 

I've been messing around a little, and here's something that I came up
with, which looks usable. Feel free to tell me what you think.

I built a variation on get_simple_tree, which for now, I called
get_dual_tree, although technically it's not a tree -- but there are no
circular references -- guaranteed. You can access data either directly,
or by traversing the ordered structure.

I started by renaming the node fields, er, hash keys, so I can simply
merge in tags with no chance of a conflict; I removed one and added
another. The renamed keys are:

	OLD	NEW	MNEMONIC
	attrib	%	perl hash
	contents	@	perl array
	name	$	perl scalar
	type	(gone)	
	(new:)	(empty)	plain text: no tags (get it?)

Each (tagged) element is represented by a hash reference; plain text is
stored directly. Thus basic rule: no reference -> text, (hash) reference
-> element. That's why you don't need the "type" key. Processing
instructions (between "<?" and "?>") are currently stored as a an array
reference; but I'm not sure you can't just drop them for this purpose.

All attributes are in an anonymous hash attached to the '%' key; the
contents are in an anonymous array attached to the '@' key. The tag's
name is in the hash entry for "$". The empty string (mnemonic: no tags)
is key for a string containing all top level text for this node. If you
don't expect any nested elements, this hash item will simply contain all
text.

That's the reserved keys. All other possible hash entries contain direct
alternative references to the contents. I always expect more than one
element for each tag, thus all values are anonymous arrays containing
references to the tagged elements.

As an example, with a record in the XML:

	<record id="a123">
	  <name>Hotel Plaza</name>
	  <title>A pleasant hotel for the whole familiy</title>
	  <images>
	    <img src="a123A"/>
	    <img src="a123B"/>
	  </images>
	</record>

then you can get the name "Hotel Plaza" by accessing

	$record->{name}[0]{''}

and the "src" attribute of the first img ("a123A") like

	$record->{images}[0]{img}[0]{'%'}{src}

Those look like many steps, I know, but it still is direct access,
there's no traversing.

Here's the code.

sub XML::Records::get_dual_tree { # method
    my $self = shift;
    return unless $self->skip_to(@_);
    my(@lists, @tree);
    my $curlist = \@tree;
    while (my $token = $self->get_token()) {
        my $type = $token->[0];
        if ($type eq 'S') {
            my $newlist = [];
            my $newnode = { '$' => $token->[1], 
	'%' => $token->[2], '@' => $newlist, '' => '' };
            push @lists, $curlist;
            push @$curlist, $newnode;
            $curlist = $newlist;
            push @{$lists[-2][-1]{$token->[1]}}, $newnode if @lists > 1;
        } elsif ($type eq 'E') {
            $curlist = pop @lists;
            @lists or last;  # top element
        } elsif ($type eq 'T') {
            push @$curlist, $token->[1];
            $lists[-1][-1]{''} .= $token->[1] if @lists;
        } elsif ($type eq 'PI') {
            push @$curlist, [ $token->[1], $token->[2] ];
        }
    }
    return $tree[0];
}

Use like (with the above sub code in this script):

	use XML::Records;
	use Data::Dumper;
	my $p = XML::Records->new('db.xml');
	$p->set_records('record');
	while (my $record = $p->get_dual_tree) {
	    print Dumper $record;
	}

-- 
	Bart.


------------------------------

Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin) 
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>


Administrivia:

The Perl-Users Digest is a retransmission of the USENET newsgroup
comp.lang.perl.misc.  For subscription or unsubscription requests, send
the single line:

	subscribe perl-users
or:
	unsubscribe perl-users

to almanac@ruby.oce.orst.edu.  

To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.

To request back copies (available for a week or so), send your request
to almanac@ruby.oce.orst.edu with the command "send perl-users x.y",
where x is the volume number and y is the issue number.

For other requests pertaining to the digest, send mail to
perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
sending perl questions to the -request address, I don't have time to
answer them even if I did know the answer.


------------------------------
End of Perl-Users Digest V10 Issue 2080
***************************************


home help back first fref pref prev next nref lref last post