package Ernad::Generate; use strict; use warnings; use Carp qw(confess); use Encode; use File::Copy; use XML::LibXML; use XML::XPath; use Ernad::Common; use Ernad::Dates; use Ernad::Constant; #use Ernad::ReportState; sub LoadAndReturnXML { my $file=shift; if (not -f $file) { confess "I don't see your file $file\n"; } open my $fh, '<', $file; binmode $fh; # drop all PerlIO layers possibly created by a use open pragma my $doc; ## protect this against a crash eval { $doc = XML::LibXML->load_xml(IO => $fh, no_network=>1); }; if(ref $doc ne 'XML::LibXML::Document') { die "I could not parse file '$file'\nLibXML says $@\n"; } return $doc; } sub amf_doc { my $amf_ns=$Ernad::Constant::c->{'amf_ns'}; my $ernad_ns=$Ernad::Constant::c->{'ernad_ns'}; my $xsi_ns='http://www.w3.org/2001/XMLSchema-instance'; my $loc='http://amf.openlib.org http://amf.openlib.org/2001/amf.xsd'; my $doc = XML::LibXML::Document->new('1.0','UTF-8'); my $amf_ele=$doc->createElementNS($amf_ns,'amf'); $amf_ele->setAttributeNS($xsi_ns, 'xsi:schemaLocation',$loc); $doc->setDocumentElement($amf_ele); return $doc; } ## same as previous function. sub load_and_return_xml { my $file=shift; if (not -f $file) { confess "fatal: no such file $file\n"; } my $fh; if($file=~m|\.gz$|) { open $fh , "/bin/gunzip -c $file |"; } else { open $fh, '<', $file; } binmode $fh; # drop all PerlIO layers possibly created by a use open pragma my $doc; ## text transformations can have the XML declaration local $XML::LibXML::skipXMLDeclaration = 1; ## protect this against a crash eval { $doc = XML::LibXML->load_xml(IO => $fh, load_ext_dtd=>0); }; if(ref $doc ne 'XML::LibXML::Document') { die "I could not parse file '$file'\nLibXML says $@\n"; } return $doc; } sub make_blank_node { my $text = XML::LibXML::Text->new(' '); return $text; } sub inject_issue_date { my $element=shift; my $issue_date=shift // ''; if(ref($element) ne 'XML::LibXML::Element') { die 'inject_issue_date called on a non-element'; } my $ERNAD_NS='http://ernad.openlib.org'; my $doc=$element->getOwner; my $issuedate_element=$doc->createElementNS($ERNAD_NS,'issuedate'); if(not $issue_date) { $issue_date = Ernad::Dates::CurrentAsString( 3 ); } $issuedate_element->appendText($issue_date); $element->appendChild($issuedate_element); $element->appendChild(&make_blank_node); return $element; } #sets url of paper sub set_delivery_url { my $text_element=shift; my $report_id=shift; my $doc=shift; #print $text_element->toString(2); my $xpc = XML::LibXML::XPathContext->new(); $xpc->registerNs('amf','http://amf.openlib.org'); $xpc->registerNs('e','http://ernad.openlib.org'); my @file_elements= $xpc->findnodes('./amf:file',$text_element); foreach my $file_element (@file_elements) { $file_element->parentNode->removeChild($file_element); } #deleting all original links # for( my $cnt = 0; $cnt < scalar( @rn ); $cnt++ ) { # $rn[$cnt]->getParentNode()->removeChild( $rn[$cnt] ); # } #bulding url #my ( $u, $r ); #$u=$n->getAttribute( "ref" );#getting paper's id #$r=$e; #$r=~s/(\S*)-(\S*)/$2/g; my $ref=$text_element->getAttribute('ref'); my $report_code=$report_id; $report_code=~s/(\S*)-(\S*)/$2/g; my $url = "http://".$Ernad::Common::Config{delivery_domain}; $url.="/n?"."u=".$ref."&r=".$report_code; #creating node for url #my ( $fnode, $unode ); #$unode = XML::XPath::Node::Element->new( "url", "" ); #XPathSetNodeText( $unode, $url ); #$fnode = XML::XPath::Node::Element->new( "file", "" ); #$fnode->appendChild( $unode ); my $nl = XML::LibXML::Text->new("\n"); my $amf_ns='http://amf.openlib.org'; my $url_element=$doc->createElementNS( $amf_ns, 'url'); $url_element->appendText($url); my $file_element=$doc->createElementNS( $amf_ns, 'file'); $text_element->appendChild($nl); $file_element->appendChild($nl); $file_element->appendChild($url_element); $file_element->appendChild($nl); $file_element->appendChild($nl); $text_element->appendChild($file_element); $text_element->appendChild($nl); return $text_element; #$n->appendChild( $fnode ); } sub CreateIssue { my $fs = $_[0]; my $line; my ( $x, @rn, @nodes ); foreach $line( @$fs ) { eval { $x = XML::XPath->new( $line ); @rn = $x->findnodes( "amf/text" ); push @nodes, @rn; }; if( $@ ) { print "Error: $@\n"; } } CreateIssueByNodes( \@nodes ); } #takes node text expressions and formats it using FormatString sub FormatNode { my $n = $_[0]; my $src = $n->string_value; Ernad::Common::XPathSetNodeText( $n, FormatString( $src ) ); } #recursively formats all child node of given sub FormatChildren { my $n = $_[0]; my @ch = $n->getChildNodes(); if( !scalar( @ch ) ) { } elsif( scalar( @ch ) == 1 && $ch[0]->isTextNode() ) { FormatNode( $n ); } else { foreach my $i( @ch ) { FormatChildren( $i ); } } } #Formats strings so it can fit into the screen sub FormatString { my $s = $_[0]; my $space; if( scalar( @_ ) > 1 ) { $space = $_[1]; } else { $space = ""; } # Remove all newlines $s =~ s/\n/ /g; # Change utf-8 space on the normal one my $ufsp = chr(194).chr(160); $s =~ s/$ufsp/ /g; # Split by letters my @letters = split( "", $s ); my $sz = 65; # Maximum string length my $ln = 0; # Current length my $wln = 0; # Length of the word my $spn = length( $space ); my $wrd = ""; my %ch = ( " " => "", "," => "", "." => "", ";" => "", ":" => "", "?" => "", "!" => "", "-" => "", "(" => "", ")" => "", chr(194).chr(160) => "" ); my $i; # For iteration my $r; # Result my $c; for($i=0 ;$i < scalar( @letters ); $i++ ) { $c = $letters[$i]; # Accumulate the text if( exists( $ch{$c} ) ) { if( $ln + 1 + $wln > $sz ) { $r .= "\n$space$wrd"; $r .= $c if( $wrd || $c != " " ); $ln = $spn + $wln; } else { $r .= "$wrd$c"; $ln += ( 1 + $wln ); } $wrd = ""; $wln = 0; } else { $wrd .= $c; $wln++; if( $wln > $sz - $spn ) { $r .= "$wrd\n$space"; $wrd = ""; $wln = 0; $ln = $spn; } } } #write last word if( $wln ) { if( $ln + $wln > $sz ) { $r .= "\n$space$wrd"; } else { $r .= $wrd; } } return $r; } 1;