My four preferences in Perl Web practices
Post on 18-Nov-2014
1896 Views
Preview:
DESCRIPTION
Transcript
My Four Preferences
My Four Preferences
in my Perl Web practice
Architecture and music
Danube
My Four Preferences
in my Perl Web practice
1. Parsing URLs with grammar
2. .ini configuration files
3. WWW::Page
4. XSLT
0. Perl 5.10
1. Parsing URLs with grammar
URL is . . .
URL is . . .
a string
URL is . . .
a string,
a set of parts
URL is . . .
a string,
a set of parts,
a container of parameters
Blog URL scheme
Blog URL scheme/
Blog URL scheme//message‐uri/
Blog URL scheme//message‐uri//tag/tag‐name/
Blog URL scheme//message‐uri//tag/tag‐name//post/
Blog URL scheme//message‐uri//tag/tag‐name//post//message‐uri/post/
Blog URL scheme//message‐uri//tag/tag‐name//post//message‐uri/post//message‐uri/comments/
How to parse?
How to parse?RewriteRules in .htaccess
How to parse?RewriteRules in .htaccess^$ /index.pl?page=home
How to parse?RewriteRules in .htaccess^$ /index.pl?page=home
^post/?$ /post.pl
How to parse?RewriteRules in .htaccess^$ /index.pl?page=home
^post/?$ /post.pl
^([^/]+)/? /index.pl?page=$1
How to parse?RewriteRules in .htaccess^$ /index.pl?page=home
^post/?$ /post.pl
^([^/]+)/? /index.pl?page=$1
etc.
How to parse?RewriteRules in .htaccess
Bad: involves programmingoutside Perl
How to parse?Regular expressions
How to parse?Regular expressionsgiven ($uri) {
when (/^\/$/) {...}
}
How to parse?Regular expressionsgiven ($uri) {
when (/^\/$/) {...}
when (/^\/post\/?/) {...}
}
How to parse?Regular expressionsgiven ($uri) {
when (/^\/$/) {...}
when (/^\/post\/?/) {...}
# (regexes as in .htaccess)
}
How to parse?Regular expressions
Bad: rules are not obvious
How to parse?split builtin
How to parse?split builtin
@parts = split m{/}, $uri;
given (scalar @parts) {
when (1) {...}
when (2) {...}
}
How to parse?split builtin
Bad: boring
How to parse?Grammars
How to parse?Grammars
Cool!
How to parse?Grammars
Cool!Easy to maintain
How to parse?Grammars
Cool!Easy to maintainBut might be slow
How to parse?Grammars
Cool!Easy to maintainBut might be slow . . .up to 100 times over regexes.
Gramars
Parse::RecDescent today
Perl 6 grammars tomorrow
Gramars
Parse::RecDescent today
Perl 6 grammars after Christmas
uri : post EOL
| view EOL
uri : post EOL
| view EOL
post : post‐message
| post‐comment
uri : post EOL
| view EOL
post : post‐message
| post‐comment
view : view‐message
| view‐tag
uri : post EOL
| view EOL
post : post‐message
| post‐comment
view : view‐message
| view‐tag
view‐message : ‘/’ word ‘/’
uri : post EOL
| view EOL
post : post‐message
| post‐comment
view : view‐message
| view‐tag
view‐message : ‘/’ word ‘/’
view‐tag : ‘/tag/’ word ‘/’
uri : post EOL
| view EOL
post : post‐message
| post‐comment
view : view‐message
| view‐tag
view‐message : ‘/’ word ‘/’
view‐tag : ‘/tag/’ word ‘/’
word : /\w+/
uri : post EOL
| view EOL
post : post‐message
| post‐comment
view : view‐message
| view‐tag
view‐message : ‘/’ word ‘/’
view‐tag : ‘/tag/’ word ‘/’
word : /\w+/
post‐message : ‘/post/’
uri : post EOL
| view EOL
post : post‐message
| post‐comment
view : view‐message
| view‐tag
view‐message : ‘/’ word ‘/’
view‐tag : ‘/tag/’ word ‘/’
word : /\w+/
post‐message : ‘/post/’
post‐comment : view‐message ‘/post/’
Actions in grammars
uri : post EOL
| view EOL
uri : post EOL {
$action = ‘post’;
}
| view EOL
uri : post EOL {
$action = ‘post’;
}
| view EOL {
$action = ‘view’;
}
view‐message : ‘/’ word ‘/’
view‐tag : ‘/tag/’ word ‘/’
view‐message : ‘/’ word ‘/’ {
$msg_sid = $item{word};
}
view‐tag : ‘/tag/’ word ‘/’
view‐message : ‘/’ word ‘/’ {
$msg_sid = $item{word};
}
view‐tag : ‘/tag/’ word ‘/’ {
$action = ‘view‐tag’;
$tag = $item{word};
}
http://example.com/twincity/
$action = ‘view’;
$msg_sid = ‘twincity’;
http://example.com/twincity/
$action = ‘view’;
$msg_sid = ‘twincity’;
http://example.com/tag/workshop/
$action = ‘view‐tag’;
$tag = ‘workshop’;
my %uri = (
'/' => {
'type' => 'index',
},
'/alpha/' => {
'type' => 'section',
'sectionUri' => 'alpha',
'sectionPage' => 1,
},
'/beta‐2/34/14/' => {
'type' => 'message',
'sectionUri' => 'beta',
'sectionPage' => 2,
'threadID' => 34,
'threadPage' => 1,
'messageID' => 14,
},
'/‐/' => {
'type' => '404',
});
for $uri (keys %uri) {
$parser‐>parse($uri);
cmp_deeply(
$parser‐>{data},
$uri{$uri},
$uri
);
}
Grammars are
logical
Grammars are
logical,
easy to extend
Grammars are
logical,
easy to extend,
cacheable
Grammars are
logical,
easy to extend,
cacheable,
easy to test
2. .ini configuration files
Application =
code + configuration
Example: blog
number of messages per page
#!/usr/bin/perl
my $MSG_PER_PAGE = 10;
#!/usr/bin/perl
my $MSG_PER_PAGE = 10;
Load configuration from external file
Load configuration from external non-Perl file
<config>
<page_length>10</page_length>
</config>
Question: XML
or JSON
or YAML
?
Answer: Windows INI
[page]
length=10
[section]
page_length=10
[thread]
page_length=10
[obsene]
replacement=***
[preview]
last_posts=31
last_message_length=200
global.ini local.ini
global.ini local.ini
[page]
length=10
[db]
host=db.int
port=3333
[db]
host=localhost
port=3306
use Config::INI::Access;
config‐>load("conf/config.ini");
use Config::INI::Access;
config‐>load("conf/config.ini");
config‐>load("conf/local.ini");
use Config::INI::Access;
config‐>load("conf/config.ini");
config‐>load("conf/local.ini");
say config‐>db‐>host;
[db]
host=localhost
port=3306
say config‐>db‐>host;
3. WWW::Page
WWW::Page
is a kinda MVC
http://example.com/some/page
/www/example.com/some/page/index.xml
http://example.com/some/page
/www/example.com/some/page/index.xml
XML
http://example.com/some/page
/www/example.com/some/page/index.xml
XML
XML
Perl
http://example.com/some/page
/www/example.com/some/page/index.xml
XML
XML
Perl
HTML
XSLT
http://example.com/some/page
/www/example.com/some/page/index.xml
XML
XML
Perl
HTML
XSLT
Browser
<?xml version="1.0" encoding="UTF‐8"?>
<page
import="Import::Client"
transform="view.xsl"
xmlns:page="urn:www‐page">
<manifest>
<title>WWW::Page Web‐Site</title>
<locale>en‐gb</locale>
<page:keyword‐list/>
</manifest>
<content>
<page:month‐calendar/>
</content>
</page>
use WWW::Page;
use encoding 'utf‐8';
my $page = new WWW::Page ({
'xslt‐root' => "../data/xsl",
});
print $page‐>as_string();
<?xml version="1.0" encoding="UTF‐8"?>
<page
import="Import::Client"
transform="view.xsl"
xmlns:page="urn:www‐page">
<manifest>
<title>WWW::Page Web‐Site</title>
<locale>en‐gb</locale>
<page:keyword‐list/>
</manifest>
<content>
<page:month‐calendar/>
</content>
</page>
<?xml version="1.0" encoding="UTF‐8"?>
<page
import="Import::Client"
transform="view.xsl"
xmlns:page="urn:www‐page">
<manifest>
<title>WWW::Page Web‐Site</title>
<locale>en‐gb</locale>
<page:keyword‐list/>
</manifest>
<content>
<page:month‐calendar/>
</content>
</page>
<?xml version="1.0" encoding="UTF‐8"?>
<page
sub Import::Client::keywordList
transform="view.xsl"
xmlns:page="urn:www‐page">
<manifest>
<title>WWW::Page Web‐Site</title>
<locale>en‐gb</locale>
<page:keyword‐list/>
</manifest>
<content>
<page:month‐calendar/>
</content>
</page>
package Import::Client;
sub keywordList { my ($this, $page, $node, $args) = @_; my $sth = $dbh‐>prepare( "select keyword, uri from keywords"); $sth‐>execute(); while (my ($keyword, $uri) = $sth‐>fetchrow_array()) { my $item = $page‐>{'xml'}‐>createElement ('item'); $item‐>appendText($keyword); $item‐>setAttribute('uri', $uri); $node‐>appendChild($item); } return $node; }
package Import::Client;
sub keywordList { my ($this, $page, $node, $args) = @_; my $sth = $dbh‐>prepare( "select keyword, uri from keywords"); $sth‐>execute(); while (my ($keyword, $uri) = $sth‐>fetchrow_array()) { my $item = $page‐>{'xml'}‐>createElement ('item'); $item‐>appendText($keyword); $item‐>setAttribute('uri', $uri); $node‐>appendChild($item); } return $node; }
package Import::Client;
sub keywordList { my ($this, $page, $node, $args) = @_; my $sth = $dbh‐>prepare( "select keyword, uri from keywords"); $sth‐>execute(); while (my ($keyword, $uri) = $sth‐>fetchrow_array()) { my $item = $page‐>{'xml'}‐>createElement ('item'); $item‐>appendText($keyword); $item‐>setAttribute('uri', $uri); $node‐>appendChild($item); } return $node; }
package Import::Client;
sub keywordList { my ($this, $page, $node, $args) = @_; my $sth = $dbh‐>prepare( "select keyword, uri from keywords"); $sth‐>execute(); while (my ($keyword, $uri) = $sth‐>fetchrow_array()) { my $item = $page‐>{'xml'}‐>createElement ('item'); $item‐>appendText($keyword); $item‐>setAttribute('uri', $uri); $node‐>appendChild($item); } return $node; }
<?xml version="1.0" encoding="UTF‐8"?>
<page
import="Import::Client"
transform="view.xsl"
xmlns:page="urn:www‐page">
<manifest>
<title>WWW::Page Web‐Site</title>
<locale>en‐gb</locale>
<page:keyword‐list/>
</manifest>
<content>
<page:month‐calendar/>
</content>
</page>
<?xml version="1.0" encoding="UTF‐8"?>
<page
import="Import::Client"
transform="view.xsl"
xmlns:page="urn:www‐page">
<manifest>
<title>WWW::Page Web‐Site</title>
<locale>en‐gb</locale>
<page:keyword‐list/>
</manifest>
<content>
<page:month‐calendar/>
</content>
</page>
<keyword‐list>
<item uri="http://perl.org/">Perl</item>
<item uri="http://dev.perl.org/">Perl 6</item>
<item uri="http://bbc.co.uk/">Perl on rails</item>
</keyword‐list>
<?xml version="1.0" encoding="UTF‐8"?>
<page
import="Import::Client"
transform="view.xsl"
xmlns:page="urn:www‐page">
<manifest>
<title>WWW::Page Web‐Site</title>
<locale>en‐gb</locale>
<keyword‐list> . . . </keyword‐list>
</manifest>
<content>
<month‐calendar> . . . </month‐calendar>
</content>
</page>
XML
HTML
XSLT
Browser
Possible improvements
<?xml version="1.0" encoding="UTF‐8"?>
<page
import="Import::Client"
transform="view.xsl"
xmlns:page="urn:www‐page">
<manifest>
<page:keyword‐list remote="host2">
</manifest>
<content>
<page:month‐calendar/>
</content>
</page>
<?xml version="1.0" encoding="UTF‐8"?>
<page
import="Import::Client"
transform="view.xsl"
xmlns:page="urn:www‐page">
<manifest>
<page:keyword‐list remote="host2">
</manifest>
<content>
<page:month‐calendar cache="memcached"/>
</content>
</page>
<?xml version="1.0" encoding="UTF‐8"?>
<page
import="Import::Client"
transform="view.xsl"
xmlns:page="urn:www‐page">
<manifest>
<page:keyword‐list remote="host2">
</manifest>
<content>
<page:month‐calendar cache="xml"/>
</content>
</page>
<?xml version="1.0" encoding="UTF‐8"?>
<page
import="Import::Client"
transform="view.xsl"
xmlns:page="urn:www‐page">
<manifest>
<page:keyword‐list remote="host2">
</manifest>
<content>
<page:month‐calendar transform="other.xsl"/>
</content>
</page>
4. XSLT
Not .WHAT XSLT is
but .WHY I use it
4a. XSLT: divide and power
website = logic + layout
website = Perl-code + HTML
website = Perl-code + XML+XSLT
website = Perl-code + XML+XSLT
Perl programmer XSLT coder
XML+XSLT
Perl programmer XSLT coder
website = Perl-code +
4b. XSLT: multiple languages
en.xml
<strings>
<months>
<item>January</item>
<item>February</item>
. . .
<item>December</item>
</months>
</strings>
de.xml
<strings>
<months>
<item>Januar</item>
<item>Februar</item>
. . .
<item>Dezember</item>
</months>
</strings>
at.xml
<strings>
<months>
<item>Jänner</item>
<item>Februar</item>
. . .
<item>Dezember</item>
</months>
</strings>
<xsl:variable name="str">
<xsl:copy‐of select="
document(
concat($lang, ‘.xml’)
)"/>
</xsl:variable>
<xsl:variable name="str">
<xsl:copy‐of select="
document(
concat($lang, ‘.xml’)
)/strings"/>
</xsl:variable>
<date day="7" month="11" year="2008"/>
<date day="7" month="11" year="2008"/>
<xsl:value‐of select="@day"/>
<date day="7" month="11" year="2008"/>
<xsl:value‐of select="@year"/>
<date day="7" month="11" year="2008"/>
<xsl:value‐of
select="$str/months/item[@month]"/>
4b. XSLT: multiple layouts
<?xml version="1.0" encoding="UTF‐8"?>
<page
import="Import::Client"
transform="view.xsl"
xmlns:page="urn:www‐page">
<manifest>
<title>WWW::Page Web‐Site</title>
<locale>en‐gb</locale>
<page:keyword‐list/>
</manifest>
<content>
<page:month‐calendar/>
</content>
</page>
<?xml version="1.0" encoding="UTF‐8"?>
<page
import="Import::Client"
transform="pda/view.xsl"
xmlns:page="urn:www‐page">
<manifest>
<title>WWW::Page Web‐Site</title>
<locale>en‐gb</locale>
<page:keyword‐list/>
</manifest>
<content>
<page:month‐calendar/>
</content>
</page>
<?xml version="1.0" encoding="UTF‐8"?>
<page
import="Import::Client"
transform="iphone/view.xsl"
xmlns:page="urn:www‐page">
<manifest>
<title>WWW::Page Web‐Site</title>
<locale>en‐gb</locale>
<page:keyword‐list/>
</manifest>
<content>
<page:month‐calendar/>
</content>
</page>
<?xml version="1.0" encoding="UTF‐8"?>
<page
import="Import::Client"
transform="rss/view.xsl"
xmlns:page="urn:www‐page">
<manifest>
<title>WWW::Page Web‐Site</title>
<locale>en‐gb</locale>
<page:keyword‐list/>
</manifest>
<content>
<page:month‐calendar/>
</content>
</page>
XML+XSLT
Perl programmer XSLT coder
website = Perl-code +
XML+XSLT
Perl programmer XSLT coder
website = Perl-code +
XSLT coder
XSLT coder
XSLT coder
__END__
Andrew Shitov
http://andy.sh | mail@andy.sh
top related