|
NAMETemplate::Semantic::Cookbook - Template::Semantic Recipes, tricks, hintsRECIPESZebra tablesUse XPath power.print Template::Semantic->process(\*DATA, { 'table tbody tr' => [ { '//td[1]' => '101', '//td[2]' => '102' }, { '//td[1]' => '201', '//td[2]' => '202' }, { '//td[1]' => '301', '//td[2]' => '302' }, { '//td[1]' => '401', '//td[2]' => '402' }, ], })->process({ '//table/tbody/tr[position() mod 2 = 0]/@class' => 'even', }); __DATA__ <table> <thead> <tr> <th>Foo</th> <th>Bar</th> </tr> </thead> <tbody> <tr class=""> <td>sample</td> <td>sample</td> </tr> </tbody> </table> Output: <table> <thead> <tr> <th>Foo</th> <th>Bar</th> </tr> </thead> <tbody> <tr class=""> <td>101</td> <td>102</td> </tr> <tr class="even"> <td>201</td> <td>202</td> </tr> <tr class=""> <td>301</td> <td>302</td> </tr> <tr class="even"> <td>401</td> <td>402</td> </tr> </tbody> </table> If you don't like "class=""", do this. print Template::Semantic->process(\*DATA, { ... )->process({ '//table//tr[position() mod 2 = 0]/@class' => 'even', '//table//tr[position() mod 2 = 1]/@class' => undef, }); For JavaScript varsIf you want to set the value for JavaScript...print $ts->process(\*DATA, { 'script[src="foo.js"]@src' => 'http://prod-server/foo.js', '//script[2]' => 'var = ' . JSON::to_json($var_to_js), }); __DATA__ <html> <script type="text/javascript" src="foo.js"></script> <script type="text/javascript"></script> ... </html> Create attributeThe following example is NOT output as "<div class="foo">foo</div>" but instead as "<div>foo</div>" because LibXML cannot find "class" attribute in "<div>".print Template::Semantic->process(\'<div>foo</div>', { 'div@class' => 'foo', }); You can add the attribute with the on-demand. print Template::Semantic->process(\'<div>foo</div>', { 'div' => sub { shift->setAttribute(class => 'foo'); \$_ }, }); But I think that you should prepare place holder. print Template::Semantic->process(\'<div class="">foo</div>', { 'div@class' => 'foo', }); Dummy itemsIf template contains dummy items to check design, you may delete them first.print Template::Semantic->process(\*DATA, { '.dummy' => undef, # remove dummys first })->process({ 'ul li' => [ { '.' => 'AAA' }, { '.' => 'BBB' }, { '.' => 'CCC' }, { '.' => 'DDD' }, { '.' => 'EEE' }, ], }); __DATA__ <ul> <li>sample</li> <li class="dummy">sample</li> <li class="dummy">sample</li> <li class="dummy">sample</li> </ul> Output: <ul> <li>AAA</li> <li>BBB</li> <li>CCC</li> <li>DDD</li> <li>EEE</li> </ul> Indicator only for Temlate::SemanticIdea 1 - Original "data-id" attribute like Template::TAL:print Template::Semantic->process(\*DATA, { '//*[@data-id="foo"]' => 'foo', '//*[@data-id="bar"]' => 'bar', })->process({ '//@data-id' => undef, }); __DATA__ <div> <span data-id="foo">xxx</span> <span data-id="bar">xxx</span> </div> Idea 2 - Original "x-foobar" class: print Template::Semantic->process(\*DATA, { '.x-foo' => 'foo', '.x-bar' => 'bar', })->process({ '//span[contains(@class,"x-")]/@class' => sub { join " ", grep { !/^x-/ } split /\s+/; }, }); __DATA__ <div> <span class="x-foo">xxx</span> <span class="x-bar">xxx</span> </div> Some custom filter ideas...Output format config in template:print Template::Semantic->process(\*DATA, { '.date' => sub { my $date = localtime; # or DateTime->now $date->strftime( shift->getAttribute('data-format') ); }, })->process({ '//@data-format' => undef, }); __DATA__ <div class="entry"> <div class="date" data-format="%Y/%m/%d">2010/99/99</div> </div> Output: <div class="entry"> <div class="date">2010/02/08</div> </div> Email template?You should use the module like Template-Toolkit ;) But if you want to use this module anyway,my $res = $ts->process(\*DATA, { 'name' => 'Foo & Co.', }); my $subj = $res->dom->documentElement->findvalue('//*[@class="subject"]'); my $body = $res->dom->documentElement->findvalue('//*[@class="body"]'); __DATA__ <html> Subject: <b class="subject">Dear <name>name</name></b> <hr /> Body: <pre class="body">Dear <name>name</name>, bla bla bla bla </pre> </html> IncludeIt is easy to substitute another "process()".my $ts = Template::Semantic->new; print $ts->process('wrapper.html', { '#container' => $ts->process('include.html'), }); Wrapper/Template inheritanceIt is possible though is tricky.my $ts = Template::Semantic->new; print $ts->process('foo.html', { '/div' => sub { my $node = shift; # Get wrapper filename from attribute ... my $wrapper = $node->getAttribute('wrapper'); # Process wrapper.html ... # embed this innerHTML to wrapper.html's <div id="content"> my $res = $ts->process($wrapper, { '#content' => \$_ }); # Insert result(as XML::LibXML::Element) after me. $node->addSibling($res->dom->documentElement); # And delete me. return undef; } })->process({ 'h1' => 'Hello world!', }); foo.html <div wrapper="wrapper.html"> <h1>foo</h1> <p>bla bla bla</p> </div> wrapper.html <html> <body> <div id="content"> </div> </body> </html> Output: <html> <body> <div id="content"> <h1>Hello world!</h1> <p>bla bla bla</p> </div> </body> </html> Do you have another good usage?Blog it ;)AUTHORNaoki Tomita <tomita@cpan.org>
Visit the GSP FreeBSD Man Page Interface. |