From 57517de73fdc8c9035726996f1a99b3493541a31 Mon Sep 17 00:00:00 2001 From: dakkar Date: Thu, 3 Jan 2008 20:23:56 +0000 Subject: refactoring: xslt git-svn-id: svn://luxion/repos/WebCoso/trunk@327 fcb26f47-9200-0410-b104-b98ab5b095f3 --- lib/WebCoso/Common.pm | 49 ++++++++++++++++++++ lib/WebCoso/TT.pm | 2 + lib/WebCoso/XSLT.pm | 95 +++++++++++++++++++++++++++++++++++++++ script/webcoso.pl | 121 +++----------------------------------------------- 4 files changed, 152 insertions(+), 115 deletions(-) create mode 100644 lib/WebCoso/XSLT.pm diff --git a/lib/WebCoso/Common.pm b/lib/WebCoso/Common.pm index 0680550..e6e5ac9 100644 --- a/lib/WebCoso/Common.pm +++ b/lib/WebCoso/Common.pm @@ -1,9 +1,16 @@ package WebCoso::Common; +use strict; +use warnings; +use Path::Class; +use XML::LibXML::XPathContext; our $SRCPATH='src'; our $DSTPATH='dst'; our $DSTBASEURL='/'; +my $xpath=XML::LibXML::XPathContext->new(); +$xpath->registerNs('x', 'http://www.w3.org/1999/xhtml'); + sub langOf { my ($name)=@_; $name=~m{(^|/)document\.([^.]+)(\.|$)} and return $2; @@ -43,4 +50,46 @@ sub isLang { return; } +sub getTitleFor { + my ($fc,$lang,$path,$name)=@_; + + my $doc_name=$name; + $doc_name=~s{\.html$}{.du.xml}; + $doc_name=~s{/$}{/document.$lang.du.xml}; + if ($doc_name=~m{^\Q$DSTBASEURL\E}) { + $doc_name=~s{^\Q$DSTBASEURL\E}{$SRCPATH/}; + } + else { + $doc_name=file($doc_name)->absolute(file($path)->parent)->relative($SRCPATH); # absolutize it + $doc_name="$SRCPATH/$doc_name"; + } + warn "getTitleFor($lang,$path,$name)->$doc_name\n"; + + my $doc=$fc->get($doc_name); + unless ($doc) { + warn "No document for <$doc_name>, returning <$name>\n"; + return $name; + } + my $title=$xpath->findnodes( + q{/document/title}, + $doc); + return $title; +} + +sub getTags { + my ($fc,@docs)=@_; + + my %tagged; + for my $doc_name (@docs) { + my $doc=$fc->get($doc_name); + my @tags=map {$_->textContent} + $xpath->findnodes( + q{/document/docinfo/field[field_name='tags']/field_body/*/list_item}, + $doc); + chomp for @tags; + push @{$tagged{$_}},$doc_name for @tags; + } + return \%tagged; +} + 1; diff --git a/lib/WebCoso/TT.pm b/lib/WebCoso/TT.pm index d04c209..fc5d114 100644 --- a/lib/WebCoso/TT.pm +++ b/lib/WebCoso/TT.pm @@ -1,4 +1,6 @@ package WebCoso::TT; +use strict; +use warnings; use WebCoso::Common; use Path::Class; use Template; diff --git a/lib/WebCoso/XSLT.pm b/lib/WebCoso/XSLT.pm new file mode 100644 index 0000000..18d2416 --- /dev/null +++ b/lib/WebCoso/XSLT.pm @@ -0,0 +1,95 @@ +package WebCoso::XSLT; +use strict; +use warnings; +use WebCoso::Common; +use Path::Class; +use XML::LibXML; +use XML::LibXSLT; + +my $NS='http://webcoso.thenautilus.net/'; + +sub new { + my ($class,%opts)=@_; + + my $self={%opts}; + + $self->{xml_parser}=XML::LibXML->new(); + $self->{xslt_proc}=XML::LibXSLT->new(); + + $self->{xslt_proc}->register_function($NS,'title-for', + sub{WebCoso::Common::getTitleFor($self->{fc},@_)}); + $self->{xslt_proc}->register_function($NS,'tagged',sub{$self->getTagsXML}); + + $self->{fc}->add_parser(qr{\.xml$} => + sub { $self->{xml_parser}->parse_string($_[1],$_[0]) }); + $self->{fc}->add_parser(qr{\.xslt?$} => + sub { $self->{xslt_proc}->parse_stylesheet + ($self->{xml_parser}->parse_string($_[1],$_[0])) }); + $self->{fc}->add_writer(qr{\.xml$} => + sub { $_[1]->toFile($_[0]) }); + + $self->{du2html}=sub { + my ($maker,$target,$deps,$matches)=@_; + + my $du=$self->{fc}->get($deps->[-1]); + my $xslt=file($deps->[-1])->parent->file('du2html.xsl'); + $xslt=$self->{fc}->get($xslt); + if (@$deps>1) { + warn "xml tagging as $deps->[0]\n"; + $self->setXMLTagsSource($self->{fc}->get($deps->[0])); + } else { + $self->setXMLTagsSource(undef); + } + my $out=$xslt->transform($du, + XML::LibXSLT::xpath_to_string( + path => $matches->[0], + language => $matches->[1], + filename => $deps->[-1], + )); + $self->{fc}->put($target,$xslt->output_string($out)); + }; + + bless $self,$class; +} + +sub du2html { + my ($self)=@_; + return $self->{du2html}; +} + +sub setXMLTagsSource { + my ($self,$source)=@_; + $self->{tags_source}=$source; +} +sub getTagsXML { + my ($self)=@_; + my $doc=XML::LibXML::Document->new(); + return $doc unless defined $self->{tags_source}; + + warn "getTagsXML()\n"; + + my $de=$doc->createElementNS($NS,'wc:tags'); + $doc->setDocumentElement($de); + my ($tagname,$doclist); + while (($tagname,$doclist)=each %{$self->{tags_source}}) { + my $te=$doc->createElementNS($NS,'wc:tag'); + $te->setAttribute('name',$tagname); + $de->appendChild($te); + my %docs; + push @{$docs{WebCoso::Common::dstUriFor($_)}},WebCoso::Common::langOf($_) for @$doclist; + my ($docurl,$langs); + while (($docurl,$langs)=each %docs) { + my $dle=$doc->createElementNS($NS,'wc:doc'); + $dle->setAttribute('uri',$docurl); + $te->appendChild($dle); + for my $lang (@$langs) { + my $le=$doc->createElementNS($NS,'wc:lang'); + $le->appendTextNode($lang); + $dle->appendChild($le); + } + } + } + return $doc; +} + +1; diff --git a/script/webcoso.pl b/script/webcoso.pl index 4803ac0..657caa8 100644 --- a/script/webcoso.pl +++ b/script/webcoso.pl @@ -4,17 +4,15 @@ use warnings; use Slay::Maker; use File::Next; use Path::Class; -use Template; use File::Cache::Parsed; use Cwd 'abs_path'; use Text::Restructured; use Text::Restructured::Writer::LibXML; -use XML::LibXML; -use XML::LibXSLT; use YAML::Syck; use Getopt::Long; use WebCoso::Common; use WebCoso::TT; +use WebCoso::XSLT; my @TMPLPATH=('common/'); my $CLEAN=0; @@ -45,11 +43,6 @@ my $rest=Text::Restructured->new( }, 'WebCoso'); -my $xml_parser=XML::LibXML->new(); -my $xslt_proc=XML::LibXSLT->new(); -my $xpath=XML::LibXML::XPathContext->new(); -$xpath->registerNs('x', 'http://www.w3.org/1999/xhtml'); - my $fc=File::Cache::Parsed->new(follow=>1); $fc->add_parser(qr{\.rest\.txt$} => sub { @@ -57,83 +50,13 @@ $fc->add_parser(qr{\.rest\.txt$} => return Text::Restructured::Writer::LibXML ->new->ProcessDOM($dudom); }); -$fc->add_parser(qr{\.xml$} => - sub { $xml_parser->parse_string($_[1],$_[0]) }); -$fc->add_parser(qr{\.xslt?$} => - sub { $xslt_proc->parse_stylesheet - ($xml_parser->parse_string($_[1],$_[0])) }); -$fc->add_writer(qr{\.xml$} => - sub { $_[1]->toFile($_[0]) }); $fc->add_parser(qr{\.ya?ml$} => sub { Load($_[1]) }); $fc->add_writer(qr{\.ya?ml$} => sub { DumpFile($_[0],$_[1]) }); my $template=WebCoso::TT->new(TMPLPATH=>\@TMPLPATH,fc=>$fc); - -sub getTitleFor { - my ($lang,$path,$name)=@_; - - my $doc_name=$name; - $doc_name=~s{\.html$}{.du.xml}; - $doc_name=~s{/$}{/document.$lang.du.xml}; - if ($doc_name=~m{^\Q$WebCoso::Common::DSTBASEURL\E}) { - $doc_name=~s{^\Q$WebCoso::Common::DSTBASEURL\E}{$WebCoso::Common::SRCPATH/}; - } - else { - $doc_name=file($doc_name)->absolute(file($path)->parent)->relative($WebCoso::Common::SRCPATH); # absolutize it - $doc_name="$WebCoso::Common::SRCPATH/$doc_name"; - } - warn "getTitleFor($lang,$path,$name)->$doc_name\n"; - - my $doc=$fc->get($doc_name); - unless ($doc) { - warn "No document for <$doc_name>, returning <$name>\n"; - return $name; - } - my $title=$xpath->findnodes( - q{/document/title}, - $doc); - return $title; -} - -my $NS='http://webcoso.thenautilus.net/'; - -$xslt_proc->register_function($NS,'title-for',\&getTitleFor); - -{my $tags_source; -sub setXMLTagsSource {$tags_source=shift} -sub getTagsXML { - my $doc=XML::LibXML::Document->new(); - return $doc unless defined $tags_source; - - warn "getTagsXML()\n"; - - my $de=$doc->createElementNS($NS,'wc:tags'); - $doc->setDocumentElement($de); - my ($tagname,$doclist); - while (($tagname,$doclist)=each %$tags_source) { - my $te=$doc->createElementNS($NS,'wc:tag'); - $te->setAttribute('name',$tagname); - $de->appendChild($te); - my %docs; - push @{$docs{WebCoso::Common::dstUriFor($_)}},WebCoso::Common::langOf($_) for @$doclist; - my ($docurl,$langs); - while (($docurl,$langs)=each %docs) { - my $dle=$doc->createElementNS($NS,'wc:doc'); - $dle->setAttribute('uri',$docurl); - $te->appendChild($dle); - for my $lang (@$langs) { - my $le=$doc->createElementNS($NS,'wc:lang'); - $le->appendTextNode($lang); - $dle->appendChild($le); - } - } - } - return $doc; -} -} -$xslt_proc->register_function($NS,'tagged',\&getTagsXML); +my $xslt=WebCoso::XSLT->new(fc=>$fc); sub parseRST { my ($maker,$target,$deps,$matches)=@_; @@ -141,42 +64,10 @@ sub parseRST { $fc->put($target,$fc->get($deps->[-1])); } -sub du2html { - my ($maker,$target,$deps,$matches)=@_; - - my $du=$fc->get($deps->[-1]); - my $xslt=file($deps->[-1])->parent->file('du2html.xsl'); - $xslt=$fc->get($xslt); - if (@$deps>1) { - warn "xml tagging as $deps->[0]\n"; - setXMLTagsSource($fc->get($deps->[0])); - } - else { - setXMLTagsSource(undef); - } - my $out=$xslt->transform($du, - XML::LibXSLT::xpath_to_string( - path => $matches->[0], - language => $matches->[1], - filename => $deps->[-1], - )); - $fc->put($target,$xslt->output_string($out)); -} - sub getTags { my ($maker,$target,$deps,$matches)=@_; - my %tagged; - for my $doc_name (@$deps) { - my $doc=$fc->get($doc_name); - my @tags=map {$_->textContent} - $xpath->findnodes( - q{/document/docinfo/field[field_name='tags']/field_body/*/list_item}, - $doc); - chomp for @tags; - push @{$tagged{$_}},$doc_name for @tags; - } - $fc->put($target,\%tagged); + $fc->put($target,WebCoso::Common::getTags($fc,@$deps)); } sub getChanges { @@ -365,7 +256,7 @@ my @passes=( "$WebCoso::Common::SRCPATH/_webcoso/tags.yml", "$WebCoso::Common::SRCPATH/tags/\$1/document.\$2.du.xml", '=', - \&du2html], + $xslt->du2html()], # normal documents, in subdirs @@ -374,7 +265,7 @@ my @passes=( "$WebCoso::Common::SRCPATH/_webcoso/tags.yml", "$WebCoso::Common::SRCPATH/\$1/document.\$2.du.xml", '=', - \&du2html], + $xslt->du2html()], # normal documents, in top dir @@ -383,7 +274,7 @@ my @passes=( "$WebCoso::Common::SRCPATH/_webcoso/tags.yml", "$WebCoso::Common::SRCPATH/document.\$2.du.xml", '=', - \&du2html], + $xslt->du2html()], ], %maker_opts, }), -- cgit v1.2.3