Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

(Updates) Re: XSLT vs Templating, Part 2

by Masem (Monsignor)
on Feb 08, 2002 at 01:32 UTC ( [id://144005]=note: print w/replies, xml ) Need Help??


in reply to XSLT vs Templating, Part 2

I've added the various suggestions in this thread: using bind_columns and prepare_cached from perrin, the use of XML::LibXML::SAX::Builder to avoid creating a temporary string, and using matts' new XML::Generator::DBI version to take advantage of the sth handler. I've also added code that uses XML::XSLT, which surprising is VERY bad at least as I've used it (did I use it wrong? I couldn't get a pure XML DOM document to work with it...)

The results are:

XML and XSLT, String Intermediate, XML::XSLT 0.159/s + -- -62% -88% -94% -95% -96% -99% + -100% XML and TT2/XPath 0.422/s + 166% -- -67% -84% -87% -90% -98% - +100% XML and TT2/Simple 1.29/s + 713% 205% -- -51% -60% -69% -95% - +99% XML and XSLT, String Intermediate, LibXSLT 2.66/s + 1573% 529% 106% -- -17% -36% -90% - +98% XML and XSLT, XML Intermediate, LibXSLT 3.20/s + 1915% 657% 148% 20% -- -23% -87% - +98% DBI and TT2 4.13/s + 2505% 879% 221% 56% 29% -- -84% - +98% DBI and CGI 25.4/s + 15931% 5924% 1873% 858% 696% 516% -- - +85% DBI and Print 172/s + 108526% 40717% 13269% 6391% 5291% 4071% 578% - +-
Nothing surprising about the order, but as you can see, with the various improvements, the behavior of LibXSLT getting close to that of DBI and TT2. There may be other improves that one could do, but as it stands, I think some of the benefits of using XSLT can outweight the small performance penalty compared to TT2 usage.

Except for changing the XSLT template as Matts indicated, the rest of the files remain unchanged. Here's the updated test code, however...

#!/usr/bin/perl -w use strict; use DBI; use CGI qw/-no_xhtml :standard/; use XML::Generator::DBI; use XML::Handler::YAWriter; use XML::LibXML::SAX::Builder; use XML::LibXML; use XML::LibXSLT; use XML::XSLT; use Template; use Data::Dumper; use Benchmark qw( cmpthese ); $Template::Config::STASH = 'Template::Stash'; my $dbh = DBI->connect( "dbi:Pg:dbname=monksdb", "", "" ) or die $DBI::errstr; my $query = "SELECT id, name, xp, lat, long FROM monks ORDER BY lat LI +MIT 25"; my $sth = $dbh->prepare_cached( $query ) or die $DBI::errstr; my $ya = XML::Handler::YAWriter->new( AsString => 1 ); my $generator = XML::Generator::DBI->new( Handler => $ya, dbh => $dbh, RowElement => "monk" ); my $generator2 = XML::Generator::DBI->new( Handler => XML::LibXML::SAX::Builder->new(), dbh => $dbh, RowElement => "monk" ); my $tt2 = Template->new; my $tt2_nonXML = "template1.tt2"; my $tt2_XML = "template2.tt2"; my $tt2_XPath = "template3.tt2"; my $parser = new XML::LibXML; my $xslt = new XML::LibXSLT; my $sheet = "xslt_sheet.xsl"; my $slt = $parser->parse_file( $sheet ); my $stylesheet = $xslt->parse_stylesheet( $slt ); my $stylesheet2 = XML::XSLT->new( $sheet, warnings => 1 ); open FILE, ">/dev/null" or die "Cannot write out: $!"; my $target = \*FILE; cmpthese( 100, { "DBI and Print" => \&generate_from_straight_dbi_and_print, "DBI and CGI" => \&generate_from_straight_dbi_and_cgi, "DBI and TT2" => \&generate_from_straight_dbi_and_tt2, "XML and TT2/Simple" => \&generate_from_xml_and_tt2_and_xmlsimp +le, "XML and TT2/XPath" => \&generate_from_xml_and_tt2_and_xpath, "XML and XSLT, String Intermediate, LibXSLT " => \&generate_fro +m_xml_and_xslt_string, "XML and XSLT, XML Intermediate, LibXSLT" => \&generate_from_xm +l_and_xslt_xml, "XML and XSLT, String Intermediate, XML::XSLT" => \&generate_fr +om_xmlxslt_xml } ); close FILE; # Here, we use straight DBI calls and print calls to mark up # the table sub generate_from_straight_dbi_and_print { # my $target = shift; $sth->execute() or die $DBI::errstr; my ( $id, $name, $xp, $lat, $long ); $sth->bind_columns( \$id, \$name, \$xp, \$lat, \$long ); print $target "Content-Type: text/html\n\n"; print $target "<html><body><table>\n"; my $colorrow = 0; while ( $sth->fetch() ) { $colorrow = !$colorrow; my $color = ( $colorrow ) ? "#FFFFFF" : "#D0D0FF"; print $target <<ROW; <tr> <td bgcolor="$color">$id</td> <td bgcolor="$color">$name</td> <td bgcolor="$color">$xp</td> <td bgcolor="$color">$lat</td> <td bgcolor="$color">$long</td> </tr> ROW ; } print $target "</table></body></html>"; } # Here, we group the results as to make it easier for CGI # to print out (avoiding large HERE docs...) sub generate_from_straight_dbi_and_cgi { # my $target = shift; $sth->execute() or die $DBI::errstr; my ( $id, $name, $xp, $lat, $long ); $sth->bind_columns( \$id, \$name, \$xp, \$lat, \$long ); my @data; while ( $sth->fetch ) { push @data, [$id, $name, $xp, $lat, $long]; +} my $colorrow = 0; print $target header('text/html'), start_html, table( map { $colorrow = !$colorrow; my $color = ( $colorrow ) ? "#FFFFFF" : "#D0D0FF"; Tr( td( {-bgcolor=>$color}, $_ ) ) } @data ), end_html; } # Here, we pass the results to Template Toolkit for printing sub generate_from_straight_dbi_and_tt2 { # my $target = shift; $sth->execute() or die $DBI::errstr; my ( $id, $name, $xp, $lat, $long ); $sth->bind_columns( \$id, \$name, \$xp, \$lat, \$long ); my @data; while ( $sth->fetch ) { push @data, [$id, $name, $xp, $lat, $long]; +} print $target header; $tt2->process( $tt2_nonXML, { monks => \@data }, $target ) or die $tt2->error(),"\n"; } # Use TT2 again, but now pass it XML and use the XPath module # for parsing sub generate_from_xml_and_tt2_and_xmlsimple { # my $target = shift; my $xml = $generator->execute( $query ); print $target header; $tt2->process( $tt2_XML, { results => $xml }, $target ) or die $tt2->error(), "\n"; } # Use TT2 again, but now pass it XML and use the XPath module # for parsing sub generate_from_xml_and_tt2_and_xpath { # my $target = shift; my $xml = $generator->execute( $query ); print $target header; $tt2->process( $tt2_XPath, { results => $xml }, $target ) or die $tt2->error(), "\n"; } # Use LibXML/LibXSLT to parse the results sub generate_from_xml_and_xslt_string { # my $target = shift; my $xml = $generator->execute( $sth ); print $target header; my $source = $parser->parse_string( $xml ); my $results = $stylesheet->transform( $source ); print $target $stylesheet->output_string( $results ); } sub generate_from_xml_and_xslt_xml { # my $target = shift; my $xml = $generator2->execute( $sth ); print $target header; my $results = $stylesheet->transform( $xml ); print $target $stylesheet->output_string( $results ); } sub generate_from_xmlxslt_xml { # my $target = shift; my $xml = $generator->execute( $sth ); print $target header; print $target $stylesheet2->serve( $xml ); }

-----------------------------------------------------
Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
"I can see my house from here!"
It's not what you know, but knowing how to find it if you don't know that's important

Replies are listed 'Best First'.
Re: (Updates) Re: XSLT vs Templating, Part 2
by gellyfish (Monsignor) on Feb 08, 2002 at 09:49 UTC

    I've also added code that uses XML::XSLT , which surprising is VERY bad at least as I've used it (did I use it wrong? I couldn't get a pure XML DOM document to work with it...)

    Heh, I discovered that there was an evil interaction between XML::Generator::DBI and XML::Handler::BuildDOM - I have sent patches to both Matt and Tim ;-}

    I'll update this later with an example of how you might do this when I get a minute

    Update: Matt has applied a fix to XML::Generator::DBI and this code now works as billed :

    #!/usr/bin/perl -w use strict; use XML::XSLT; use XML::Generator::DBI; use XML::Handler::BuildDOM; use XML::DOM; use DBI; my $ya = XML::Handler::BuildDOM->new(); my $dbh = DBI->connect("dbi:Informix:tdcusers",'','',{ChopBlanks => 1} +); my $generator = XML::Generator::DBI->new( Handler => $ya, dbh => $dbh ); my $style =<<EOFOO; <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" versi +on="1.0"> <xsl:output encoding = "iso-8859-1"/> <xsl:template match = "select"> <html> <head> <title> Test </title> </head> <body> <table> <xsl:for-each select="row"> <tr> <td> <xsl:value-of select="prefix" /> </td> <td> <xsl:value-of select="code" /> </td> <td> <xsl:value-of select="ctext" /> </td> </tr> </xsl:for-each> </table> </body> </html> </xsl:template> </xsl:stylesheet> EOFOO my $stylesheet = XML::XSLT->new($style); my $sql = 'select * from text_codes'; my $dom = $generator->execute($sql); $stylesheet->transform(Source => $dom); $stylesheet->toString();

    You will obviously want to use your own database and an appropriate stylesheet :)

    /J\

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://144005]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (8)
As of 2024-03-28 09:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found