After thinking out loud in my last post, here is some new code that 
illustrates how to do generic replacement processing with on-the-fly 
formatting... It is a quick perl script but is basically the guts for a 
my:sub XMLSubs-type function...


#! /bin/perl

my $body = << "EOF";
<fmt>PRICE:%.2f,AGE:%3d,STATE:%uc2</fmt>
Price \$__PRICE__ - You must be __AGE__ years old to buy in __STATE__.
EOF

my %hash = (
        price   => 12,
        age     => 18,
        state   => 'va',
        );

my %fmt = (); # for format view

## extract format (if any) - what's left becomes template string
$body =~ s/<fmt>(.*?)<\/fmt>//i;
$fmt = $1;

## scoop-up formats into a convenient hash
foreach (split(/,/, $fmt)) {
        my ($key, $val) = split(/:/, $_);
        $fmt{uc(eatwhite($key))} = eatwhite($val);
        }

## render hash using template string and format hash
render($body, \%hash, \%fmt);

sub render { ## process template using data in hash and formatting info
        my $tmpl = shift;
        my $hash = shift;
        my $fmt = shift;

        foreach (keys %$hash) {
                my $key = uc($_);
                if ($$fmt{$key} ne undef) {
                        my $fmt = $$fmt{$key};
                        if ($fmt =~ /^%uc/i) { # to-uppercase
                                $fmt =~ s/[^0-9]//g;
                                $$hash{$_} = uc(substr($$hash{$_}, 0, $fmt || 
length($$hash{$_})));
                                }
                        elsif ($fmt =~ /^%lc/i) { # to-lowercase
                                $fmt =~ s/[^0-9]//g;
                                $$hash{$_} = lc(substr($$hash{$_}, 0, $fmt  || 
length($$hash{$_})));
                                }
                        else { # picture
                                $$hash{$_} = sprintf($fmt, $$hash{$_});
                                }
                        }
                $tmpl =~ s/__${key}__/$$hash{$_}/gie;
                }
        print "$tmpl\n";
        }

## convenience function
sub eatwhite { $_[0] =~ s/^\s*(.*?)\s*$/$1/; return $_[0] };

__END__


This script simulates the guts of the following XMLSubs scenario:

<my:sub ...>
<fmt>PRICE:%.2f,AGE:%3d,STATE:%uc2</fmt>
Price \$__PRICE__ - You must be __AGE__ years old to buy in __STATE__.
</my:sub>


The format info is scooped-up into the %fmt hash and each item in the hash is 
processed according to its format data, if available. Otherwise its just 
directly replaced. Two pseudo formats are also available: %lcN and %ucN 
(where N is a positive integer representing the max chars to return -- N can 
also be left off in which case the entire string will be processed and 
returned).

This type of processing would simplify _many_ chores-- for example, consider 
this hypothetical example in which "my:sub" retrieves one or more rows of 
data and then renders them according to the body info:


<table>
<my:sub search="search_string" >
<fmt>COST:%.2f,PRICE:%.2f</fmt>
<tr><td>__PART__</td><td>__NAME__</td><td>__DESCR__</td><td>__COST__</td><td>__PRICE__</td></tr>
</my:sub>
</table>

And that would be pretty much the WHOLE html file. All of the nasty bits are 
hidden away in the 'my:sub' functionality.


Another interesting way to process vars, and more in keeping with the JSP 
Taglib stuff you mentioned (I did some reading today ;) would be a script 
similar to this:

#! /bin/perl

## script to test matching parameters

my $str1 = "NAME: John AGE: 40 SEX: M";
my $str2 = "NAME: Wendy AGE: 42 SEX: F";
my $str3 = "NAME: Scott SSN: 36 SEX: M";
my $str4 = "NAME: Beck AGE: 30 SEX: F";
my @fields = qw(name age sex);
my $pat = 'NAME: (.*?) AGE: (\d+) SEX: (.*)$';

print "STR: '$str'\n";
print "PAT: /$pat/\n";
print "\n";

foreach ($str1, $str2, $str3, $str4) {
        my $hash = extractData($_, $pat, \@fields);
        if ($hash eq undef) { print "WARNING - Encountered bad data\n" }
        else { foreach (keys %$hash) { print "KEY = $_, VAL = $$hash{$_}\n" }}
        print "-"x72, "\n";
        }

sub extractData {
        my $str = shift;
        my $pat = shift;
        my $fields = shift;
        my $count = 0;
        my %h = ();
        $str =~ /$pat/;
        while (${++$count} ne undef) { $h{$$fields[$count-1]} = ${$count} }
        return \%h if ($count-1 == scalar @$fields); # correct field count
        return undef; # bad field count
        }

__END__

This script simulates the $1, $2, $3 functionality of pattern matching but in 
such a way that any number of pattern-tokens can be matched and returned 
without knowing the exact number beforehand-- this way a generic pattern 
processor can be used to apply a pattern against a string and return the 
matched data. This script does not use the exact %1, %2, %3 syntax that 
Taglibs calls for, but that's a minor issue and could be worked in. The 
harder part was coming up with a way to work iterate the $1, $2.. vars which 
don't like to be iterated. This code snippet was not actually originally for 
an ASP script, but when Josh mentioned that bit about the JSP Taglibs and I 
read up on it, this snippet immediately came to mind. I can't imagine that it 
would be that hard to adapt to the concept.


As always, I hope someone might find some of this stuff useful, informative, 
or at least interesting ;)

John Whitten
[EMAIL PROTECTED]
Wizard.Org, Inc.



-- 

--------------------------------------------------------------------------------
Check out http://www.Wizard.Org for great deals on Electronic Parts
*NEW* Computer Parts & Accessories - Drives - LCD - Systems - Linux
--------------------------------------------------------------------------------
** Affordable Online Store w/Merchant Card Processing & Paypal **
Write to us: [EMAIL PROTECTED]  --  Get your Store Online Today!
--------------------------------------------------------------------------------



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to