package WebCoso::XSLT; use strict; use warnings; use WebCoso::Common; use Path::Class; use XML::LibXML; use XML::LibXSLT; use DateTime::Format::Strptime; use Log::Log4perl ':easy'; 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{$self->getTitleXML(WebCoso::Common::getTitleFor($self->{fc},@_))}); $self->{xslt_proc}->register_function($NS,'tagged',sub{$self->getTagsXML}); $self->{xslt_proc}->register_function($NS,'dates-for', sub{$self->getDatesXML(WebCoso::Common::getDatesFor($self->{fc},@_))}); $self->{xslt_proc}->register_function($NS,'message', sub{DEBUG($_[0],' ',$_[1]->get_node(0)->toString());return ''}); $self->{xslt_proc}->debug_callback(sub{DEBUG(@_)}); $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)=@_; DEBUG("du2html($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) { INFO("xml tag source from as $deps->[0]"); $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)); }; $self->{fillFeed}=sub { my ($maker,$target,$deps,$matches)=@_; DEBUG("fillFeed($maker,$target,(@$deps),(@$matches))"); my $du=$self->{fc}->get($deps->[-1]); my $xslt=file($deps->[-1])->parent->file('fillFeed.xsl'); $xslt=$self->{fc}->get($xslt); if (@$deps>1) { INFO("xml tag source from $deps->[0]"); $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 fillFeed { my ($self)=@_; return $self->{fillFeed}; } 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}; 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||'ERRORE'); $te->appendChild($dle); for my $lang (@$langs) { my $le=$doc->createElementNS($NS,'wc:lang'); $le->appendTextNode($lang); $dle->appendChild($le); } } } return $doc; } { my %name_map=(creation=>'wc:creation-date', last_change=>'wc:last-change'); my $format=DateTime::Format::Strptime->new(pattern=>'%F %T',time_zone=>'UTC'); sub getDatesXML { my ($self,$dates)=@_; my $doc=XML::LibXML::Document->new(); return $doc unless defined $dates; my $de=$doc->createElementNS($NS,'wc:dates'); $doc->setDocumentElement($de); while (my ($k,$v)=each %$dates) { my $d=$doc->createElementNS($NS,$name_map{$k}); $d->appendTextNode($format->format_datetime($v)); $de->appendChild($d); } return $doc; } } sub getTitleXML { my ($self,$title)=@_; return $title if ref($title) && ($title->isa('XML::LibXML::Node') || $title->isa('XML::LibXML::NodeList')); my $doc=XML::LibXML::Document->new(); my $de=$doc->createElement('paragraph'); $doc->setDocumentElement($de); $de->appendTextNode($title); return $doc; } 1;