M.C.P.C.

―むり・くり―プラスコミュニケーション(更新終了)


| トップページ |

2011年6月22日 22:02

ウェブサイトの過去ニュース管理用MovableType風スクリプト

このエントリーをはてなブックマークに追加 mixiチェック

ウェブサイトの過去のニュースを、個別ページとして生成させたくなって、XMLをソースとした書き出しシステム(MovableType風)ができたので、それのソースです。Linuxのコマンドラインで実行します。

Filename: past.pl

#!/usr/bin/perl
 
use strict;
use warnings;
use utf8;
use DateTime::Format::W3CDTF;
use Encode;
use FindBin::Real;
use File::Path;
use File::Spec;
use File::Basename;
use HTML::Template;
use XML::LibXML;
use YAML;
binmode STDOUT => ':utf8';
 
chdir FindBin::Real::Bin();
 
my $sourcefile    = 'news.xml';
my $individualtmplfile = 'tmpl/individual.tmpl';
my $baseurl       = 'http://www.example.com/past/';
my @index_template = qw(
   tmpl/index.html.tmpl
   tmpl/sitemap.txt
);
 
# XMLファイルを一気読み
open my $fh, '<', $sourcefile or die $!;
my $source = do { local $/; <$fh> };
 
# XMLパース&処理
my $list = xmlparse($source);
 
# Publish前データ処理
pre_publish(\$list);
 
# individual archive処理
{
  my $t = HTML::Template->new(
    filename => $individualtmplfile,
    filter   => sub { utf8::decode( ${ shift() } ); },
    die_on_bad_params => 0,
  );
  map {
    $t->param( $_ );
    open $fh, '>', $_->{file} or die $!;
    binmode $fh => ':utf8';
    print $fh $t->output;
    close $fh;
  } @$list;
}
 
# index template処理
map{ main_index( $_ ); } @index_template;
 
exit;
 
 
# XMLパース
sub xmlparse {
  my $source = shift;
  # XML::LibXMLパーザ
  my $parser = XML::LibXML->new(
   suppress_errors    => 1,
    suppress_warnings => 1,
    recover           => 2,
  );
  my $dom = $parser->parse_string($source);
  
  # DOMインタフェースでノードリスト選択
  my @xfolk = $dom->findnodes('//o:xfolkentry');
  
  # XMLから要素を読み込む(ここでは読み込む専門、加工は最低限)
  foreach my $x ( @xfolk ) {
    my $body;
    foreach my $i ( $x->find('o:body')->[0]->childNodes ) {
      $body .= $i->toString();
    }
    my $description = $x->findvalue('o:body');
    my $extended_body;
    if ( $x->exists('o:extended_body') ) {
      foreach my $i ( $x->find('o:extended_body')->[0]->childNodes ) {
        $extended_body .= $i->toString();
      }
      $description .= $x->findvalue('o:extended_body');
    }
    my $items =  {
      date  => $x->findvalue('o:date'),
      title => $x->findvalue('o:title'), 
      body  => $body,
      extended_body  => $extended_body,
      description    => $description,
    };
    #$items->{extended_body} = $extended_body if $extended_body;
    push @$list, $items;
  }
  return $list;
}
 
# XMLから解析済みの要素
sub pre_publish {
  my $lst = shift;
  map {
    my $dt = DateTime::Format::W3CDTF->parse_datetime($_->{date})->set_time_zone('Asia/Tokyo');
    my $filepath = $dt->strftime('%Y/%m');
    mkpath $filepath;
    my $date_id = $dt->strftime('%Y%m%d');
    my $basename = $_->{basename}
      || $dt->strftime('%m%d%H%M%S').".html";
    print "$filepath/$basename\n";
    $_->{basename} = $basename;
    $_->{filepath} = $filepath;
    $_->{datetime} = "$dt";
    $_->{ymd}      = $dt->ymd;
    $_->{date_id}  = $date_id;
    $_->{permalink} = "${baseurl}$filepath/$basename";
    $_->{file}     = "$filepath/$basename";
  } @$$lst;
}
 
# index template書き出し テンプレート名を入れると
# テンプレート名から.tmplをとったファイルで
# カレントディレクトリへ書き出します。
sub main_index {
  my $tmplfile = shift;
  my $t = HTML::Template->new(
    filename => $tmplfile,
    filter   => sub { utf8::decode( ${ shift() } ); },
    die_on_bad_params => 0,
    loop_context_vars => 1,
  );
  $t->param( list => $list, baseurl => $baseurl );
  my $outputfile = fileparse($tmplfile, ".tmpl");
  open $fh, '>', $outputfile or die $!;
  binmode $fh => ':utf8';
  print $fh $t->output;
  close $fh;
}
 
__END__


XMLは、こんな感じです。


Filename: news.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 
<o:info
  xmlns="http://www.w3.org/1999/xhtml"
  xmlns:o="http://www.example.com/">
  
  <o:xfolkentry>
    <o:date>2011-07-01</o:date>
    <o:title>計画停電実施に伴う営業時間の短縮について</o:title>
    <o:body>
      <p>当地区では2011年7月1日午後9時~午後12時まで、計画停電が実施されることになりました。</p>
      <p>つきましては、営業時間を短縮させていただきますのでお知らせします。</p>
    </o:body>
    <o:extended_body>
      <dl>
        <dt>営業時間</dt>
        <dd>午後1時~午後18時</dd>
      </dl>
      <p>社員の帰宅時の交通安全を確保する目的で、停電終了時刻から1時間遅れて営業を開始いたします。ご理解のほどよろしくお願いします。</p>
    </o:extended_body>
  </o:xfolkentry>
</o:info>

o:ていうプリフィクスは名前空間です。こうやると、XHTMLの名前空間は省略できるのですね。

のこり、テンプレート。

Filename: tmpl/index.html.tmpl

<!DOCTYPE html>
<html>
  <head profile="http://microformats.org/profile/xfolk">
    <meta charset="utf-8">
    <title>
      過去のニュース
    </title>
  </head>
  <body>
    <article class="xfolkentry" id="d<tmpl_var name="date_id">">
      <p><tmpl_var name="ymd"></p>
      <h3><a href="<tmpl_var name="filepath">/<tmpl_var name="basename">"><tmpl_var name="title"></a></h3>
      <tmpl_var name="body">
      <tmpl_if name="extended_body">
      <p style="text-align: right;">
        <a href="<tmpl_var name="filepath">/<tmpl_var name="basename">#more">続きを読む</a></p>
      </tmpl_if>
    </article>
    </tmpl_loop>
  </body>
</html>


Filename: sitemap.txt.inc

<tmpl_loop name="list"><tmpl_var name="permalink">
</tmpl_loop><tmpl_var name="baseurl">


Filename: tmpl/individual.tmpl

<!DOCTYPE html>
<html>
  <head profile="http://microformats.org/profile/xfolk">
    <meta charset="utf-8">
    <title>
      <tmpl_var name="title">
    </title>
  </head>
  <body>
    <article class="xfolkentry" id="d<tmpl_var name="date_id">">
      <p><tmpl_var name="date"></p>
      <h3><tmpl_var name="title"></h3>
      <div id="body">
        <tmpl_var name="body">
      </div>
      <div id="more">
        <tmpl_var name="extended_body">
      </div>
      <div class="metadata">
       <a href="<tmpl_var name="permalink">"><tmpl_var name="date"></a>
      </div>
    </article>
  </body>
</html>

~~~

大体3時間でできたので、MovableTypeやWordPress入れるよりもかえって早いぐらいだと思うんですが、CMSを自作しても将来性がないのでWordPress入れたほうがいいよ、て言われるとグウの音も出ないよね……

投稿 大野 義貴 [Perl] | |

トラックバック(0)

トラックバックURL: http://blog.dtpwiki.jp/MTOS/mt-tb.cgi/3625

コメントする