summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/crossrefware
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2014-10-19 22:36:21 +0000
committerKarl Berry <karl@freefriends.org>2014-10-19 22:36:21 +0000
commit85fe62616c2d0cda42038452c38374f1cf5d855a (patch)
tree45a4890dc18b6bd0d1e6142eeebf19ee293c10a3 /Master/texmf-dist/scripts/crossrefware
parentc07d0b959c7e9bbc2b3beeeab1ebf9ab11489255 (diff)
crossrefware (19oct14)
git-svn-id: svn://tug.org/texlive/trunk@35401 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/scripts/crossrefware')
-rwxr-xr-xMaster/texmf-dist/scripts/crossrefware/bibdoiadd.pl267
-rwxr-xr-xMaster/texmf-dist/scripts/crossrefware/bibzbladd.pl215
-rwxr-xr-xMaster/texmf-dist/scripts/crossrefware/ltx2crossrefxml.pl460
3 files changed, 942 insertions, 0 deletions
diff --git a/Master/texmf-dist/scripts/crossrefware/bibdoiadd.pl b/Master/texmf-dist/scripts/crossrefware/bibdoiadd.pl
new file mode 100755
index 00000000000..b9be8dec824
--- /dev/null
+++ b/Master/texmf-dist/scripts/crossrefware/bibdoiadd.pl
@@ -0,0 +1,267 @@
+#!/usr/bin/env perl
+
+=pod
+
+=head1 NAME
+
+bibdoiadd.pl - add DOI numbers to papers in a given bib file
+
+=head1 SYNOPSIS
+
+bibdoiadd [B<-c> I<config_file>] [B<-o> I<output>] I<bib_file>
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-c> I<config_file>
+
+Configuration file. If this file is absent, some defaults are used.
+See below for its format.
+
+
+=item B<-o> I<output>
+
+Output file. If this option is not used, the name for the
+output file is formed by adding C<_doi> to the input file
+
+=back
+
+=head1 DESCRIPTION
+
+The script reads a BibTeX file. It checks whether the entries have
+DOIs. If now, tries to contact http://www.crossref.org to get the
+corresponding DOI. The result is a BibTeX file with the fields
+C<doi=...> added.
+
+The name of the output file is either set by the B<-o> option or
+is derived by adding the suffix C<_doi> to the output file.
+
+There are two options for making queries with Crossref: free account
+and paid membership. In the first case you still must register with
+Crossref and are limited to a small number of queries, see the
+agreement at
+C<http://www.crossref.org/01company/free_services_agreement.html>. In
+the second case you have a username and password, and can use them for
+automatic queries. I am not sure whether the use of this script is
+allowed for the free account holders. Anyway if you try to add DOI
+to a large number of entries, you should register as a paid member.
+
+
+
+=head1 CONFIGURATION FILE
+
+The configuration file is mostly self-explanatory: it has comments
+(starting with C<#>) and assginments in the form
+
+ $field = value ;
+
+The important parameters are C<$mode> (C<'free'> or C<'paid'>,
+C<$email> (for free users) and C<$username> & C<$password> for paid
+members.
+
+
+=head1 EXAMPLES
+
+ bibdoiadd -c bibdoiadd.cfg citations.bib > result.bib
+ bibdoiadd -c bibdoiadd.cfg citations.bib -o result.bib
+
+=head1 AUTHOR
+
+Boris Veytsman
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2014 Boris Veytsman
+
+This is free software. You may redistribute copies of it under the
+terms of the GNU General Public License
+L<http://www.gnu.org/licenses/gpl.html>. There is NO WARRANTY, to the
+extent permitted by law.
+
+=cut
+
+use strict;
+use Text::BibTeX;
+use Text::BibTeX::Name;
+use Getopt::Std;
+use URI::Escape;
+use LWP::Simple;
+use TeX::Encode;
+use Encode;
+use HTML::Entities;
+use XML::Entities;
+
+my $USAGE="USAGE: $0 [-c config] [-o output] file\n";
+my $VERSION = <<END;
+bibdoiadd v1.0
+This is free software. You may redistribute copies of it under the
+terms of the GNU General Public License
+http://www.gnu.org/licenses/gpl.html. There is NO WARRANTY, to the
+extent permitted by law.
+$USAGE
+END
+my %opts;
+getopts('c:o:hV',\%opts) or die $USAGE;
+
+if ($opts{h} || $opts{V}){
+ print $VERSION;
+ exit 0;
+}
+
+################################################################
+# Defaults and parameters
+################################################################
+
+my $inputfile = shift;
+
+my $outputfile = $inputfile;
+
+$outputfile =~ s/\.([^\.]*)$/_doi.$1/;
+
+if ($opts{o}) {
+ $outputfile = $opts{o};
+}
+
+our $mode='free';
+our $email;
+our $username;
+our $password;
+
+if ($opts{c}) {
+ if (-r $opts{c}) {
+ push @INC, ".";
+ require $opts{c};
+ } else {
+ die "Cannot read options $opts{c}. $USAGE";
+ }
+}
+
+
+# Check the consistency
+
+if ($mode eq 'free' && !length($email)) {
+ die "Crossref requires a registered e-mail for the free mode queries\n";
+}
+
+if ($mode eq 'paid' && (!length($username) || !length($password))) {
+ die
+ "Crossref requires a username and password for the paid mode queries\n";
+}
+
+my $input = new Text::BibTeX::File "$inputfile" or
+ die "Cannot BibTeX file $inputfile\n";
+my $output = new Text::BibTeX::File "> $outputfile" or
+ die "Cannot write to $outputfile\n";
+
+my $prefix =
+ "http://www.crossref.org/openurl?redirect=false";
+if ($mode eq 'free') {
+ $prefix .= '&pid='.uri_escape($email);
+} else {
+ $prefix .= '&pid='.uri_escape($username).":".
+ uri_escape($password);
+}
+
+# Processing the input
+while (my $entry = new Text::BibTeX::Entry $input) {
+ if (!$entry->parse_ok()) {
+ print STDERR "Cannot understand entry: ";
+ $entry->print(*STDERR);
+ print STDERR "Skipping this entry\n";
+ next;
+ }
+ if (!(($entry->metatype() eq BTE_REGULAR) &&
+ ($entry->type() eq 'article'))) {
+ $entry->write($output);
+ next;
+ }
+ if ($entry->exists('doi')) {
+ $entry->write($output);
+ next;
+ }
+
+
+ # Now we have an entry with no doi. Let us get to work.
+ my $doi = GetDoi($prefix,$entry);
+ if (length($doi)) {
+ $entry->set('doi',$doi);
+ }
+ $entry->write($output);
+
+}
+
+$input->close();
+$output->close();
+exit 0;
+
+###############################################################
+# Getting one doi
+###############################################################
+
+sub GetDoi {
+ my ($url,$entry) = @_;
+ if ($entry->exists('issn')) {
+ $url .= "&issn=".uri_escape(SanitizeText($entry->get('issn')));
+ }
+ if ($entry->exists('journal')) {
+ $url .= "&title=".uri_escape(SanitizeText($entry->get('journal')));
+ }
+ my @names=$entry->names ('author');
+ if (scalar(@names)) {
+ my @lastnames = $names[0]->part ('last');
+ if (scalar(@lastnames)) {
+ my $lastname = SanitizeText(join(' ',@lastnames));
+ $url .= "&aulast=".uri_escape($lastname);
+ }
+ }
+ if ($entry->exists('volume')) {
+ $url .= "&volume=".uri_escape($entry->get('volume'));
+ }
+ if ($entry->exists('number')) {
+ $url .= "&issue=".uri_escape($entry->get('number'));
+ }
+ if ($entry->exists('pages')) {
+ my $pages=$entry->get('pages');
+ $pages =~ s/-.*$//;
+ $url .= "&spage=".uri_escape($pages);
+ }
+ if ($entry->exists('year')) {
+ $url .= "&date=".uri_escape($entry->get('year'));
+ }
+
+ my $result=get($url);
+
+ if ($result =~ m/<doi [^>]*>(.*)<\/doi>/) {
+ return $1;
+ } else {
+ return "";
+ }
+}
+
+###############################################################
+# Sanitization of a text string
+###############################################################
+sub SanitizeText {
+ my $string = shift;
+ # There is a bug in the decode function, which we need to work
+ # around: it adds space to constructions like \o x
+ $string =~ s/(\\[a-zA-Z])\s+/$1/g;
+ $string =~ s/\\newblock//g;
+ $string =~ s/\\urlprefix//g;
+ $string =~ s/\\emph//g;
+ $string =~ s/\\enquote//g;
+ $string =~ s/\\url/URL: /g;
+ $string =~ s/\\doi/DOI: /g;
+ $string =~ s/\\\\/ /g;
+ $string = decode('latex', $string);
+ $string =~ s/\\[a-zA-Z]+/ /g;
+ $string =~ s/\\\\/ /g;
+ $string =~ s/[\[\{\}\]]/ /g;
+ $string = encode_entities($string);
+ $string = XML::Entities::numify('all', $string);
+ $string =~ s/amp;//g;
+ $string =~ s/~/ /g;
+ $string =~ s/\s*([\.;,])/$1/g;
+ return $string;
+}
diff --git a/Master/texmf-dist/scripts/crossrefware/bibzbladd.pl b/Master/texmf-dist/scripts/crossrefware/bibzbladd.pl
new file mode 100755
index 00000000000..4059b7b0a12
--- /dev/null
+++ b/Master/texmf-dist/scripts/crossrefware/bibzbladd.pl
@@ -0,0 +1,215 @@
+#!/usr/bin/env perl
+
+=pod
+
+=head1 NAME
+
+bibzbladd.pl - add Zbl numbers to papers in a given bib file
+
+=head1 SYNOPSIS
+
+bibzbladd [B<-o> I<output>] I<bib_file>
+
+=head1 OPTIONS
+
+=over 4
+
+
+=item B<-o> I<output>
+
+Output file. If this option is not used, the name for the
+output file is formed by adding C<_zbl> to the input file
+
+=back
+
+=head1 DESCRIPTION
+
+The script reads a BibTeX file. It checks whether the entries have
+Zbls. If now, tries to contact internet to get the numbers. The
+result is a BibTeX file with the fields
+C<zblnumber=...> added.
+
+The name of the output file is either set by the B<-o> option or
+is derived by adding the suffix C<_zbl> to the output file.
+
+=head1 AUTHOR
+
+Boris Veytsman
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2014 Boris Veytsman
+
+This is free software. You may redistribute copies of it under the
+terms of the GNU General Public License
+L<http://www.gnu.org/licenses/gpl.html>. There is NO WARRANTY, to the
+extent permitted by law.
+
+=cut
+
+use strict;
+use Text::BibTeX;
+use Text::BibTeX::Name;
+use Getopt::Std;
+use URI::Escape;
+use LWP::UserAgent;
+use TeX::Encode;
+
+my $USAGE="USAGE: $0 [-o output] file\n";
+my $VERSION = <<END;
+bibzbladd v1.0
+This is free software. You may redistribute copies of it under the
+terms of the GNU General Public License
+http://www.gnu.org/licenses/gpl.html. There is NO WARRANTY, to the
+extent permitted by law.
+$USAGE
+END
+my %opts;
+getopts('o:hV',\%opts) or die $USAGE;
+
+if ($opts{h} || $opts{V}){
+ print $VERSION;
+ exit 0;
+}
+
+################################################################
+# Defaults and parameters
+################################################################
+
+my $inputfile = shift;
+
+my $outputfile = $inputfile;
+
+$outputfile =~ s/\.([^\.]*)$/_zbl.$1/;
+
+if ($opts{o}) {
+ $outputfile = $opts{o};
+}
+
+my $input = new Text::BibTeX::File "$inputfile" or
+ die "Cannot BibTeX file $inputfile\n";
+my $output = new Text::BibTeX::File "> $outputfile" or
+ die "Cannot write to $outputfile\n";
+
+
+# Creating the HTTP parameters
+my $mirror =
+ "http://www.zentralblatt-math.org/MIRROR/zmath/en/search/";
+my $userAgent = LWP::UserAgent->new;
+
+# Processing the input
+while (my $entry = new Text::BibTeX::Entry $input) {
+ if (!$entry->parse_ok()) {
+ print STDERR "Cannot understand entry: ";
+ $entry->print(*STDERR);
+ print STDERR "Skipping this entry\n";
+ next;
+ }
+ if (!(($entry->metatype() eq BTE_REGULAR))) {
+ $entry->write($output);
+ next;
+ }
+ if ($entry->exists('zblnumber')) {
+ $entry->write($output);
+ next;
+ }
+
+
+ # Now we have an entry with no Zbl. Let us get to work.
+ my $zbl = GetZbl($entry, $userAgent, $mirror);
+ if (length($zbl)) {
+ $entry->set('zblnumber',$zbl);
+ }
+ $entry->write($output);
+
+}
+
+$input->close();
+$output->close();
+exit 0;
+
+###############################################################
+# Getting one Zbl
+###############################################################
+
+sub GetZbl {
+ my $entry=shift;
+ my $userAgent=shift;
+ my $mirror=shift;
+
+ my @query;
+
+ my @names=$entry->names ('author');
+ if (scalar(@names)) {
+ foreach my $name (@names) {
+ my @lastnames = $name->part ('last');
+ if (scalar(@lastnames)) {
+ foreach my $lastname (@lastnames) {
+ push @query, "au:$lastname";
+ }
+ }
+ }
+ }
+ if (my $title = $entry->get('title')) {
+ push @query, "ti:$title";
+ }
+
+ if (my $year = $entry->get('year')) {
+ push @query, "py:$year";
+ }
+
+ if (my $year = $entry->get('year')) {
+ push @query, "py:$year";
+ }
+
+ my $type = $entry->type;
+ if ($type eq 'article') {
+ push @query, "dt:j";
+ }
+ if ($type eq 'book') {
+ push @query, "dt:b";
+ }
+ if ($type eq 'inproceedings' || $type eq 'incollection') {
+ push @query, "dt:a";
+ }
+
+ my $source = "";
+ if ($type eq 'article') {
+ if ($entry->get('journal')) {
+ $source .= $entry->get('journal');
+ }
+ if (my $vol=$entry->get('volume')) {
+ $source .= ",$vol";
+ }
+ if (my $pages=$entry->get('pages')) {
+ $source .= ",$pages";
+ }
+ } else {
+ if (my $bt=$entry->get('booktitle')) {
+ $source .= "$bt";
+ }
+ }
+
+ if ($source) {
+ push @query, "so:$source";
+ }
+
+
+ my $qstring = join(" & ", @query);
+# print STDERR "$qstring\n";
+
+ my $form;
+
+ $form->{name}='form';
+ $form->{q} = $qstring;
+ $form->{type} = "ascii";
+ $form->{submit} = 'Search';
+
+ my $response = $userAgent->post($mirror, $form);
+ if ($response->decoded_content =~ /^an:\s*Zbl\s*(\S+)\s*$/m) {
+ return $1;
+ } else {
+ return ("");
+ }
+}
+
diff --git a/Master/texmf-dist/scripts/crossrefware/ltx2crossrefxml.pl b/Master/texmf-dist/scripts/crossrefware/ltx2crossrefxml.pl
new file mode 100755
index 00000000000..5ceee5f13df
--- /dev/null
+++ b/Master/texmf-dist/scripts/crossrefware/ltx2crossrefxml.pl
@@ -0,0 +1,460 @@
+#!/usr/bin/env perl
+
+=pod
+
+=head1 NAME
+
+ltx2crossrefxml.pl - a tool for creation of XML files for submitting to crossref.
+
+=head1 SYNOPSIS
+
+ltx2crossrefxml [B<-c> I<config_file>] [B<-o> I<output>] I<latex_file> I<latex_file> ...
+
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-c> I<config_file>
+
+Configuration file. If this file is absent, some defaults are used.
+See below for its format.
+
+
+=item B<-o> I<output>
+
+Output file. If this option is not used, the XML is output to stdout.
+
+=back
+
+=head1 DESCRIPTION
+
+The script takes a number of latex files and produces an XML file
+ready for submission to Crossref. Each file must be previously processed
+by LaTeX with the newest C<resphilosophica> package: the package creates
+the file C<.rti> wtih the information about the bibliography.
+
+The processing of reference list is at present rather limited: only so
+called unstructured references are produced.
+
+=head1 CONFIGURATION FILE FORMAT
+
+The configuration file is mostly self-explanatory: it has comments
+(starting with C<#>) and assginments in the form
+
+ $field = value ;
+
+=head1 EXAMPLES
+
+ ltx2crossrefxml.pl ../paper1/paper1.tex ../paper2/paper2.tex -o result.xml
+
+ ltx2crossrefxml.pl -c myconfig.cnf paper.tex -o paper.xml
+
+=head1 AUTHOR
+
+Boris Veytsman
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2012 Boris Veytsman
+
+This is free software. You may redistribute copies of it under the
+terms of the GNU General Public License
+L<http://www.gnu.org/licenses/gpl.html>. There is NO WARRANTY, to the
+extent permitted by law.
+
+
+=cut
+
+ use strict;
+ use POSIX qw(strftime);
+ use Text::BibTeX;
+ use Text::BibTeX::Name;
+ use TeX::Encode;
+ use Encode;
+ use HTML::Entities;
+ use XML::Entities;
+ use File::Basename;
+ use File::Spec;
+ my $USAGE="USAGE: $0 [-c config] [-o output] file1 file2 ...\n";
+my $VERSION = <<END;
+ltx2crossrefxml v1.0
+This is free software. You may redistribute copies of it under the
+terms of the GNU General Public License
+http://www.gnu.org/licenses/gpl.html. There is NO WARRANTY, to the
+extent permitted by law.
+$USAGE
+END
+ use Getopt::Std;
+ my %opts;
+ getopts('c:o:hV',\%opts) or die $USAGE;
+
+if ($opts{h} || $opts{V}){
+ print $VERSION;
+ exit 0;
+}
+
+ ################################################################
+ # Defaults and parameters
+ ################################################################
+
+ *OUT=*STDOUT;
+
+ if (defined($opts{o})) {
+ open (OUT, ">$opts{o}") or die "Cannot open file $opts{o} for writing\n";
+ }
+
+
+ our $depositorName='DEPOSITOR_NAME';
+ our $depositorEmail='DEPOSITOR_EMAIL';
+ our $registrant='REGISTRANT';
+ our $fullTitle = "FULL TITLE";
+ our $abbrevTitle = "ABBR. Title.";
+ our $issn = "1234-5678";
+ our $coden = "CODEN";
+ our $batchId="ltx2crossref$$";
+ our $timestamp=strftime("%Y%m%d%H%M%S", gmtime);
+
+
+ if ($opts{c}) {
+ if (-r $opts{c}) {
+ require $opts{c};
+ } else {
+ die "Cannot read options $opts{c}. $USAGE";
+ }
+ }
+
+
+
+ PrintHead();
+
+ #
+ # The hash %papers. Keys year->vol->issue->number
+ #
+ my %papers;
+
+ foreach my $file (@ARGV) {
+ AddPaper($file);
+ }
+
+ foreach my $year (keys %papers) {
+ foreach my $volume (keys %{$papers{$year}}) {
+ foreach my $issue (keys %{$papers{$year}->{$volume}}) {
+ PrintIssueHead($year, $volume, $issue);
+ my $paperList = $papers{$year}->{$volume}->{$issue};
+ foreach my $paper (@{$paperList}) {
+ PrintPaper($paper);
+ }
+ }
+ }
+
+ }
+
+ PrintTail();
+
+ exit(0);
+
+
+#####################################################
+# Printing the head and the tail
+#####################################################
+
+sub PrintHead {
+
+
+ print OUT <<END;
+<doi_batch xmlns="http://www.crossref.org/schema/4.3.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="4.3.0" xsi:schemaLocation="http://www.crossref.org/schema/4.3.0 http://www.crossref.org/schema/deposit/crossref4.3.0.xsd">
+ <head>
+ <doi_batch_id>$batchId</doi_batch_id>
+ <timestamp>$timestamp</timestamp>
+ <depositor>
+ <name>$depositorName</name>
+ <email_address>$depositorEmail</email_address>
+ </depositor>
+ <registrant>$registrant</registrant>
+ </head>
+ <body>
+ <journal>
+ <journal_metadata language="en">
+ <full_title>$fullTitle</full_title>
+ <abbrev_title>$abbrevTitle</abbrev_title>
+ <issn>$issn</issn>
+ <coden>$coden</coden>
+ </journal_metadata>
+END
+
+}
+
+sub PrintTail {
+ print OUT <<END;
+ </journal>
+ </body>
+</doi_batch>
+END
+
+return;
+}
+
+
+#######################################################
+# Adding one paper
+#######################################################
+
+sub AddPaper {
+ my $file = shift;
+ my ($name,$path,$suffix) = fileparse($file, '\.[^\.]*$');
+ my $rpifile = File::Spec->catfile($path, "$name.rpi");
+ open (RPI, $rpifile) or die
+ "Cannot find $rpifile. Did you process $file?\n";
+ my %data;
+ while (<RPI>) {
+ chomp;
+ if (/^%([^=]*)\s*=\s*(.*)\s*$/) {
+ $data{$1}=$2;
+ }
+ }
+ close RPI;
+ my @bibliography;
+ foreach my $bibfile ($file, File::Spec->catfile($path, "$name.bbl")) {
+ @bibliography = (@bibliography,
+ AddBibliography($bibfile));
+ }
+ $data{'bibliography'}=\@bibliography;
+ push @{$papers{$data{year}}->{$data{volume}}->{$data{issue}}}, \%data;
+}
+
+##############################################################
+# Reading a list of papers and adding it to the
+# bibliography
+##############################################################
+
+sub AddBibliography {
+ my $bibfile = shift;
+ open (BIB, $bibfile) or return;
+ my $insidebibliography = 0;
+ my $currpaper="";
+ my @result;
+ my $key;
+ while (<BIB>) {
+ chomp;
+ if (/^\s*\\bibitem(?:\[.*\])?+\{(.+)\}/) {
+ if ($insidebibliography) {
+ if ($currpaper) {
+ my %paperhash;
+ $paperhash{$key}=$currpaper;
+ push @result, \%paperhash;
+ }
+ }
+ $key = $1;
+ $currpaper="";
+ $insidebibliography=1;
+ next;
+ }
+ if (/^\s*\\end\{thebibliography\}/) {
+ if ($currpaper) {
+ my %paperhash;
+ $paperhash{$key}=$currpaper;
+ push @result, \%paperhash;
+ }
+ $currpaper="";
+ $insidebibliography=0;
+ next;
+ }
+ if ($insidebibliography) {
+ $currpaper .= " $_";
+ }
+ }
+ close BIB;
+ return @result;
+}
+
+#################################################################
+# Printing information about one issue
+#################################################################
+
+sub PrintIssueHead {
+ my ($year, $volume, $issue) = @_;
+ print OUT <<END;
+ <journal_issue>
+ <publication_date media_type="print">
+ <year>$year</year>
+ </publication_date>
+ <journal_volume>
+ <volume>$volume</volume>
+ </journal_volume>
+ <issue>$issue</issue>
+ </journal_issue>
+END
+}
+
+###############################################################
+# Printing information about one paper
+###############################################################
+sub PrintPaper {
+ my $paper = shift;
+ my $title=SanitizeText($paper->{title});
+ my $url=GetURL($paper);
+ print OUT <<END;
+ <journal_article publication_type="full_text">
+ <titles>
+ <title>
+ $title
+ </title>
+ </titles>
+ <contributors>
+END
+my @authors = split /\s*\\and\s*/, $paper->{authors};
+ my $seq='first';
+ foreach my $author (@authors) {
+ print OUT <<END;
+ <person_name sequence="$seq" contributor_role="author">
+END
+$seq='additional';
+ PrintAuthor($author);
+ print OUT <<END;
+ </person_name>
+END
+
+ }
+
+ print OUT <<END;
+ </contributors>
+ <publication_date media_type="print">
+ <year>$paper->{year}</year>
+ </publication_date>
+ <pages>
+ <first_page>$paper->{startpage}</first_page>
+ <last_page>$paper->{endpage}</last_page>
+ </pages>
+ <doi_data>
+ <doi>$paper->{doi}</doi>
+ <timestamp>$timestamp</timestamp>
+ <resource>$url</resource>
+ </doi_data>
+END
+
+if (scalar(@{$paper->{bibliography}})) {
+ print OUT <<END;
+ <citation_list>
+END
+ foreach my $citation (@{$paper->{bibliography}}) {
+ PrintCitation($citation);
+ }
+ print OUT <<END;
+ </citation_list>
+END
+}
+
+ print OUT <<END;
+ </journal_article>
+END
+
+
+}
+
+
+###############################################################
+# Sanitization of a text string
+###############################################################
+sub SanitizeText {
+ my $string = shift;
+ # There is a bug in the decode function, which we need to work
+ # around: it adds space to constructions like \o x
+ $string =~ s/(\\[a-zA-Z])\s+/$1/g;
+ $string =~ s/\\newblock//g;
+ $string =~ s/\\bgroup//g;
+ $string =~ s/\\egroup//g;
+ $string =~ s/\\scshape//g;
+ $string =~ s/\\urlprefix//g;
+ $string =~ s/\\emph//g;
+ $string =~ s/\\textbf//g;
+ $string =~ s/\\enquote//g;
+ $string =~ s/\\url/URL: /g;
+ $string =~ s/\\doi/DOI: /g;
+ $string =~ s/\\\\/ /g;
+ $string =~ s/\$//g;
+ $string = decode('latex', $string);
+ $string =~ s/\\[a-zA-Z]+/ /g;
+ $string =~ s/\\\\/ /g;
+ $string =~ s/[\[\{\}\]]/ /g;
+ $string = encode_entities($string);
+ $string = XML::Entities::numify('all', $string);
+ $string =~ s/amp;//g;
+ $string =~ s/~/ /g;
+ $string =~ s/\s*([\.;,])/$1/g;
+ return $string;
+}
+
+################################################################
+# Printing one author
+################################################################
+sub PrintAuthor {
+ my $author=shift;
+
+ my $person=new Text::BibTeX::Name ($author);
+
+ if ($person->part('first')) {
+ my @tokens = $person->part('first');
+ my $line = join(" ", @tokens);
+ $line = SanitizeText($line);
+ print OUT <<END;
+ <given_name>$line</given_name>
+END
+
+ }
+
+ if ($person->part('last')) {
+ my $line = SanitizeText($person->part('last'));
+ print OUT <<END;
+ <surname>$line</surname>
+END
+
+ }
+
+ if ($person->part('jr')) {
+ my $line = SanitizeText($person->part('jr'));
+ print OUT <<END;
+ <suffix>$line</suffix>
+END
+
+ }
+
+}
+
+#############################################################
+# Printing citations
+#############################################################
+sub PrintCitation {
+ my $paperhash=shift;
+ foreach my $key (keys (%{$paperhash})) {
+ my $citation=$paperhash->{$key};
+ $citation=SanitizeText($citation);
+
+ print OUT <<END;
+ <citation key="$key">
+ <unstructured_citation>
+ $citation
+ </unstructured_citation>
+ </citation>
+END
+}
+
+}
+
+##############################################################
+# Calculating URL
+##############################################################
+
+sub GetURL {
+ my $paper = shift;
+
+ my $result;
+ if ($paper->{paperUrl}) {
+ $result= $paper->{paperUrl}
+ } else {
+ my $doi=$paper->{doi};
+ $result= 'http://www.pdcnet.org/oom/service?url_ver=Z39.88-2004&rft_val_fmt=&rft.imuse_synonym=resphilosophica&rft.DOI='.$doi.'&svc_id=info:www.pdcnet.org/collection';
+ }
+ $result =~ s/&/&#38;/g;
+ return $result;
+}