#!/usr/bin/perl

##########################################################################
#
# xml2rtf
# Converts a XML-file into Microsofts(TM) "Rich Text Format" (RTF).
#
# Written & Copyright (C) 2014, 2015 by Peer Schaefer (peer@wolldingwacht.de).
# Licensed under the GNU General Public Licence, version 2 or later (at
# your choice).
#
##########################################################################

use strict;
use warnings;
use utf8;
use Encode;
use File::Temp qw/tempfile/;

my $VERSION        = "0.93";

#####################################################################
# Configuration:
#####################################################################

my $xslt_processor = "";
my $verbose        = 0;
my $xsl_text       = "";
my $xml_text       = "";
my $xml_filename   = "";
my $rtf_filename   = "";
my $dump_flag      = 0;

#####################################################################
# Read arguments:
#####################################################################

sub print_help();
sub read_file($);
sub fetch_buildin_xsl();

foreach( @ARGV ) {
    if ( /^-{1,2}(h|help)$/ ) {
	print_help();
	exit 1;
    }
    elsif ( /^-{1,2}(version)$/ ) {
	print STDERR "xml2rtf version ${VERSION}.\n";
	exit 1;
    }
    elsif ( /^-{1,2}(d|dump)$/ ) {
	$dump_flag = 1;
    }
    elsif ( /^-{1,2}(libxslt)$/ ) {
	$xslt_processor = "libxslt";
    }
    elsif ( /^-{1,2}(xsltproc)$/ ) {
	$xslt_processor = "xsltproc";
    }
    elsif ( /^-{1,2}(verbose)$/ ) {
	$verbose++;
    }
    elsif ( /^-{1,2}(v+)$/ ) {
	$verbose += length( $1 );
    }
    elsif ( /^-{1,2}(xml)=(.+?)$/ ) {
	if ( $xml_text eq "" ) {
	    $xml_text = $2;
	}
	else {
	    die "Please specify only one XML source";
	}
    }
    elsif ( ( -e $_ ) and ( /\.(xml|XML)$/ ) ) {
	if ( $xml_text eq "" ) {
	    $xml_filename = $_;
	    $xml_text     = read_file( $xml_filename );
	}
	else {
	    die "Please specify only one XML source";
	}
    }
    elsif ( ( -e $_ ) and ( /\.(xslt*|XSLT*)$/ ) ) {
	if ( $xsl_text eq "" ) {
	    $xsl_text = read_file( $_ );
	}
	else {
	    die "Please specify only one XSLT file";
	}
    }
    elsif ( ( -e $_ ) and ( /\.(rtf|RTF)$/ ) ) {
	if ( $rtf_filename eq "" ) {
	    $rtf_filename = $_;
	}
	else {
	    die "Please specify only one output file";
	}
    }
    else {
	die "Syntax error: $_";
    }
}

#####################################################################
# Sane defaults:
#####################################################################

if ( $xml_text eq "" ) {
    $xml_text = read_file( "-" );
}
if ( $xsl_text eq "" ) {
    $xsl_text = fetch_buildin_xsl();
    if ( not( $xml_text =~ /^\s*\<document\>/s ) ) {
	$xml_text = "<document>${xml_text}</document>";
	if ( $verbose >= 1 ) {
	    print STDERR "Automagically providing <document> envelope.\n";
	}
    }
}
if ( $dump_flag == 1 ) {
    $rtf_filename = "-";
}
else {
    if ( $rtf_filename eq "" ) {
	if ( $xml_filename =~ /^(.+?)\.(xml|XML)$/ ) {
	    $rtf_filename = $1 . ".rtf";
	}
	else {
	    $rtf_filename = "-";
	}
    }
}

#####################################################################
# Find XSLT-processor:
#####################################################################

my $xsltproc;
if ( $xslt_processor eq "" ) {
    if ( ( `perl -MXML::LibXSLT -e 1 2>&1` =~ /^\s*$/ ) and ( `perl -MXML::LibXML -e 1 2>&1` =~ /^\s*$/ ) ) {
	$xslt_processor = "libxslt";
    }
    elsif ( ( defined `xsltproc --version 2>&1` ) and ( `xsltproc --version 2>&1` =~ /(libxml|libxslt)/s ) ) {
	$xslt_processor = "xsltproc";
    }
    else {
	die "No XSLT-processing facility found";
    }
}

#####################################################################
# Define XSLT-processor:
#####################################################################

if ( $xslt_processor eq "libxslt" ) {
    if ( ( `perl -MXML::LibXSLT -e 1 2>&1` =~ /^\s*$/ ) and ( `perl -MXML::LibXML -e 1 2>&1` =~ /^\s*$/ ) ) {
	if ( $verbose >= 1 ) {
	    print STDERR "Using XML::LibXSLT.\n";
	}
	eval "use XML::LibXSLT;";
	eval "use XML::LibXML;";
	die "$@" if $@;
	$xsltproc = sub {
	    my $xml_parser  = XML::LibXML->new();
	    my $xsl         = $xml_parser->load_xml( string => shift( @_ ) );
	    my $xml         = $xml_parser->load_xml( string => shift( @_ ) );
	    my $xslt_parser = XML::LibXSLT->new();
	    my $stylesheet  = $xslt_parser->parse_stylesheet( $xsl );
	    my $results     = $stylesheet->transform( $xml );
	    my $output      = $stylesheet->output_string( $results );
	    return $output;
	};
    }
    else {
	die "XML::LibXSLT not installed";
    }
}
elsif ( $xslt_processor eq "xsltproc" ) {
    if ( ( defined `xsltproc --version 2>&1` ) and ( `xsltproc --version 2>&1` =~ /(libxml|libxslt)/s ) ) {
	if ( $verbose >= 1 ) {
	    print STDERR "Using xsltproc.\n";
	}
	$xsltproc = sub {
	    my $xsl = shift( @_ );
	    my $xml = shift( @_ );
	    my ( $fh_xsl, $fn_xsl ) = tempfile(); binmode $fh_xsl; print $fh_xsl encode( "utf-8", $xsl );
	    my ( $fh_xml, $fn_xml ) = tempfile(); binmode $fh_xml; print $fh_xml encode( "utf-8", $xml );
	    my ( $fh_out, $fn_out ) = tempfile();
	    my $result = `xsltproc -o \"${fn_out}\" \"${fn_xsl}\" \"${fn_xml}\" 2>&1`;
	    if ( $result =~ /^\s*$/ ) {
		my $text = "";
		binmode $fh_out;
		while( <$fh_out> ) {
		    $text .= $_;
		}
		return decode( "Windows-1252", $text );
	    }
	    else {
		die "Error processing xsltproc: ${result}";
	    }
	}
    }
    else {
	die "Error: xsltproc not installed";
    }
}
else {
    die "Neither XML::LibXSLT nor xsltproc installed.";
}

#####################################################################
# MAIN:
#####################################################################

my $result = &$xsltproc ( $xsl_text, $xml_text );
if ( $rtf_filename eq "-" ) {
    binmode STDOUT;
    print STDOUT encode( "Windows-1252", $result ), "\n";
}
else {
    open( my $rtf_fh, ">", $rtf_filename ) or die $!;
    binmode $rtf_fh;
    print $rtf_fh encode( "Windows-1252", $result ), "\n";
    close $rtf_fh;
}
exit 0;

#####################################################################
# SUBROUTINES:
#####################################################################

sub print_help()
{
    print "Usage: xml2rtf [OPTIONs] [FILEs]\n";
    print "Converts a XML-file into Microsofts(TM) \"Rich Text Format\" (RTF).\n";
    print "\n";
    print " -h, --help      display this help and exit\n";
    print " --verbose       be verbose\n";
    print " -d, --dump      write output to STDOUT\n";
    print " --libxslt       use Perls XML::LibXSLT library\n";
    print " --xsltproc      use the external program \"xsltproc\"\n";
    print " --xml=\"TEXT\"    use TEXT as XML source\n";
    print "\n";
    print "If no XML-file is specified, the program reads from STDIN.\n";
    print "If no XSLT-stylesheet is specified, the program uses a build-in default stylesheet.\n";
    print "If no RTF-filename is specified, the program creates a filename from the filename of the XML-file and appends \".rtf\" (or, if input is taken from STDIN, it outputs to STDOUT).\n";
    print "\n";
    print "Examples:\n";
    print "xml2rtf                 reads XML from STDIN and writes RTF to STDOUT.\n";
    print "xml2rtf name.xml        reads \"name.xml\" and writes output to \"name.rtf\".\n";
    print "xml2rtf name.xml --dump reads \"name.xml\" and writes output to STDOUT\".\n";
    print "\n";
    print "Tags:\n";
    print "The build-in stylesheet recognizes the following tags:\n";
    print " <document>             encloses the whole document\n";
    print " <document format=\"FORMAT\"> uses FORMAT (\"a4\" or \"letter\")\n";
    print " <p>                    paragraph\n";
    print " <p align=\"ALIGNMENT\">  paragraph, aligned left, right, centered or justified\n";
    print " <i>                    italics\n";
    print " <b>                    bold\n";
    print " <ul>                   underlined\n";
    print " <strike>               strike through\n";
    print " <caps>                 all caps\n";
    print " <smallcaps>            all caps with lowercase in smaller caps\n";
    print " <outline>              outline font\n";
    print " <font face=\"FONTNAME\"> use font FONTNAME\n";
    print " <font color=\"COLOR\">   use color COLOR (standard HTML/CSS-names are recognized)\n";
    print " <font size=\"POINTS\">   use size POINTS (standard is 12)\n";
    print "\n";
    print "xml2rtf version ${VERSION}. Written & Copyright (C) 2014, 2015 by Peer Schaefer (peer\@wolldingwacht.de). Licensed under the GNU General Public Licence (GPL), version 2 or later (at your choice). This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GPL for more details.\n";
    exit 1;
}

sub fetch_buildin_xsl()
{
    my $xsl = "";
    while( <DATA> ) {
	$xsl .= $_;
    }
    return $xsl;
}

sub guess_encoding($);

sub read_file($)
{
    my $filename = shift( @_ );
    my $encoding;
    my $text     = "";
    if ( $filename eq "-" ) {
	binmode STDIN;
	while( <STDIN> ) {
	    $text .= $_;
	}
	my( $tmpfh, $tmpfn ) = tempfile();
	binmode $tmpfh;
	print $tmpfh $text;
	$encoding = guess_encoding( $tmpfn );
    }
    else {
	open( my $fh, "<", $filename ) or die $!;
	binmode $fh;
	while( <$fh> ) {
	    $text .= $_;
	}
	close $fh;
	$encoding = guess_encoding( $filename );
    }
    return decode( $encoding, $text );
}

sub guess_encoding($)
{
    my $filename = shift( @_ );
    if ( ( defined `file --version 2>&1` ) and ( `file --version 2>&1` =~ /magic/s ) ) {
	if ( `file --mime --brief \"${filename}\"` =~ /\scharset=([^\s\;]+)/ ) {
	    my $encoding = $1;
	    if ( $verbose >= 1 ) {
		print STDERR "Guessed encoding for \"${filename}\": ${encoding}.\n";
	    }
	    return $encoding;
	}
	else {
	    die "Can't identify encoding";
	}
    }
    else {
	my @popular_encodings = (
	    "utf-8",
	    "iso-8859-1",
	    "cp1252",
	    "cp1250"
	    );
	open( my $fh, "<", $filename ) or die $!;
	binmode $fh;
	my $text = "";
	while( <$fh> ) {
	    $text .= $_;
	}
	close $fh;
	foreach my $encoding ( @popular_encodings ) {
	    eval { decode( $encoding, $text, Encode::FB_CROAK ) };
	    if ( not $@ ) {
		if ( $verbose >= 1 ) {
		    print STDERR "Guessed encoding for \"${filename}\": ${encoding}.\n";
		}
		return $encoding;
	    }
	}
    }
    die "Can't identify encoding";
}

#####################################################################
# Build-in XSLT-stylesheet follows behind "__END__":
#####################################################################
__END__
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.w3.org/1999/xhtml">

  <xsl:strip-space elements="*" /> 
  <xsl:preserve-space elements="" />

  <xsl:output method="text" encoding="Windows-1252" indent="no" />

  <xsl:variable name="faces"  select="//font/@face[not(.=following::font/@face)]" />
  <xsl:variable name="colors" select="//font/@color[not(.=following::font/@color)]" />
 
  <xsl:template match="document">

    <xsl:text>{\rtf1\ansi\ansicpg1252{</xsl:text>

    <xsl:if test="(./@format='a4') or (./@format='A4')"><xsl:text>\paperw11906\paperh16838</xsl:text></xsl:if>
    <xsl:if test="(./@format='letter') or (./@format='us-letter') or (./@format='Letter') or (./@format='US-Letter')"><xsl:text>\paperw12240\paperh15840</xsl:text></xsl:if>

    <xsl:if test="count($faces)>0">
      <xsl:text>{\fonttbl {</xsl:text>
      <xsl:for-each select="$faces">
	<xsl:text>\f</xsl:text>
	<xsl:variable name="facename"><xsl:value-of select="." /></xsl:variable>
	<xsl:for-each select="$faces">
	  <xsl:if test=".=$facename">
	    <xsl:value-of select="position()" />
	  </xsl:if>
	</xsl:for-each>
	<xsl:text> </xsl:text>
	<xsl:value-of select="." />
	<xsl:text>;</xsl:text>
      </xsl:for-each>
      <xsl:text>}}</xsl:text>
    </xsl:if>

    <xsl:if test="count($colors)>0">
      <xsl:text>{\colortbl;</xsl:text>
      <xsl:for-each select="$colors">
	<xsl:if test="(.='AliceBlue') or (.='aliceblue')"><xsl:text>\red240\green248\blue255;</xsl:text></xsl:if>
	<xsl:if test="(.='AntiqueWhite') or (.='antiquewhite')"><xsl:text>\red250\green235\blue215;</xsl:text></xsl:if>
	<xsl:if test="(.='Aqua') or (.='aqua')"><xsl:text>\red0\green255\blue255;</xsl:text></xsl:if>
	<xsl:if test="(.='Aquamarine') or (.='aquamarine')"><xsl:text>\red127\green255\blue212;</xsl:text></xsl:if>
	<xsl:if test="(.='Azure') or (.='azure')"><xsl:text>\red240\green255\blue255;</xsl:text></xsl:if>
	<xsl:if test="(.='Beige') or (.='beige')"><xsl:text>\red245\green245\blue220;</xsl:text></xsl:if>
	<xsl:if test="(.='Bisque') or (.='bisque')"><xsl:text>\red255\green228\blue196;</xsl:text></xsl:if>
	<xsl:if test="(.='Black') or (.='black')"><xsl:text>\red0\green0\blue0;</xsl:text></xsl:if>
	<xsl:if test="(.='BlanchedAlmond') or (.='blanchedalmond')"><xsl:text>\red255\green235\blue205;</xsl:text></xsl:if>
	<xsl:if test="(.='Blue') or (.='blue')"><xsl:text>\red0\green0\blue255;</xsl:text></xsl:if>
	<xsl:if test="(.='BlueViolet') or (.='blueviolet')"><xsl:text>\red138\green43\blue226;</xsl:text></xsl:if>
	<xsl:if test="(.='Brown') or (.='brown')"><xsl:text>\red165\green42\blue42;</xsl:text></xsl:if>
	<xsl:if test="(.='BurlyWood') or (.='burlywood')"><xsl:text>\red222\green184\blue135;</xsl:text></xsl:if>
	<xsl:if test="(.='CadetBlue') or (.='cadetblue')"><xsl:text>\red95\green158\blue160;</xsl:text></xsl:if>
	<xsl:if test="(.='Chartreuse') or (.='chartreuse')"><xsl:text>\red127\green255\blue0;</xsl:text></xsl:if>
	<xsl:if test="(.='Chocolate') or (.='chocolate')"><xsl:text>\red210\green105\blue30;</xsl:text></xsl:if>
	<xsl:if test="(.='Coral') or (.='coral')"><xsl:text>\red255\green127\blue80;</xsl:text></xsl:if>
	<xsl:if test="(.='CornflowerBlue') or (.='cornflowerblue')"><xsl:text>\red100\green149\blue237;</xsl:text></xsl:if>
	<xsl:if test="(.='Cornsilk') or (.='cornsilk')"><xsl:text>\red255\green248\blue220;</xsl:text></xsl:if>
	<xsl:if test="(.='Crimson') or (.='crimson')"><xsl:text>\red220\green20\blue60;</xsl:text></xsl:if>
	<xsl:if test="(.='Cyan') or (.='cyan')"><xsl:text>\red0\green255\blue255;</xsl:text></xsl:if>
	<xsl:if test="(.='DarkBlue') or (.='darkblue')"><xsl:text>\red0\green0\blue139;</xsl:text></xsl:if>
	<xsl:if test="(.='DarkCyan') or (.='darkcyan')"><xsl:text>\red0\green139\blue139;</xsl:text></xsl:if>
	<xsl:if test="(.='DarkGoldenrod') or (.='darkgoldenrod')"><xsl:text>\red184\green134\blue11;</xsl:text></xsl:if>
	<xsl:if test="(.='DarkGray') or (.='darkgray')"><xsl:text>\red169\green169\blue169;</xsl:text></xsl:if>
	<xsl:if test="(.='DarkGrey') or (.='darkgrey')"><xsl:text>\red169\green169\blue169;</xsl:text></xsl:if>
	<xsl:if test="(.='DarkGreen') or (.='darkgreen')"><xsl:text>\red0\green100\blue0;</xsl:text></xsl:if>
	<xsl:if test="(.='DarkKhaki') or (.='darkkhaki')"><xsl:text>\red189\green183\blue107;</xsl:text></xsl:if>
	<xsl:if test="(.='DarkMagenta') or (.='darkmagenta')"><xsl:text>\red139\green0\blue139;</xsl:text></xsl:if>
	<xsl:if test="(.='DarkOliveGreen') or (.='darkolivegreen')"><xsl:text>\red85\green107\blue47;</xsl:text></xsl:if>
	<xsl:if test="(.='DarkOrange') or (.='darkorange')"><xsl:text>\red255\green140\blue0;</xsl:text></xsl:if>
	<xsl:if test="(.='DarkOrchid') or (.='darkorchid')"><xsl:text>\red153\green50\blue204;</xsl:text></xsl:if>
	<xsl:if test="(.='DarkRed') or (.='darkred')"><xsl:text>\red139\green0\blue0;</xsl:text></xsl:if>
	<xsl:if test="(.='DarkSalmon') or (.='darksalmon')"><xsl:text>\red233\green150\blue122;</xsl:text></xsl:if>
	<xsl:if test="(.='DarkSeaGreen') or (.='darkseagreen')"><xsl:text>\red143\green188\blue143;</xsl:text></xsl:if>
	<xsl:if test="(.='DarkSlateBlue') or (.='darkslateblue')"><xsl:text>\red72\green61\blue139;</xsl:text></xsl:if>
	<xsl:if test="(.='DarkSlateGray') or (.='darkslategray')"><xsl:text>\red47\green79\blue79;</xsl:text></xsl:if>
	<xsl:if test="(.='DarkSlateGrey') or (.='darkslategrey')"><xsl:text>\red47\green79\blue79;</xsl:text></xsl:if>
	<xsl:if test="(.='DarkTurquoise') or (.='darkturquoise')"><xsl:text>\red0\green206\blue209;</xsl:text></xsl:if>
	<xsl:if test="(.='DarkViolet') or (.='darkviolet')"><xsl:text>\red148\green0\blue211;</xsl:text></xsl:if>
	<xsl:if test="(.='DeepPink') or (.='deeppink')"><xsl:text>\red255\green20\blue147;</xsl:text></xsl:if>
	<xsl:if test="(.='DeepSkyBlue') or (.='deepskyblue')"><xsl:text>\red0\green191\blue255;</xsl:text></xsl:if>
	<xsl:if test="(.='DimGray') or (.='dimgray')"><xsl:text>\red105\green105\blue105;</xsl:text></xsl:if>
	<xsl:if test="(.='DimGrey') or (.='dimgrey')"><xsl:text>\red105\green105\blue105;</xsl:text></xsl:if>
	<xsl:if test="(.='DodgerBlue') or (.='dodgerblue')"><xsl:text>\red30\green144\blue255;</xsl:text></xsl:if>
	<xsl:if test="(.='FireBrick') or (.='firebrick')"><xsl:text>\red178\green34\blue34;</xsl:text></xsl:if>
	<xsl:if test="(.='FloralWhite') or (.='floralwhite')"><xsl:text>\red255\green250\blue240;</xsl:text></xsl:if>
	<xsl:if test="(.='ForestGreen') or (.='forestgreen')"><xsl:text>\red34\green139\blue34;</xsl:text></xsl:if>
	<xsl:if test="(.='Fuchsia') or (.='fuchsia')"><xsl:text>\red255\green0\blue255;</xsl:text></xsl:if>
	<xsl:if test="(.='Gainsboro') or (.='gainsboro')"><xsl:text>\red220\green220\blue220;</xsl:text></xsl:if>
	<xsl:if test="(.='GhostWhite') or (.='ghostwhite')"><xsl:text>\red248\green248\blue255;</xsl:text></xsl:if>
	<xsl:if test="(.='Gold') or (.='gold')"><xsl:text>\red255\green215\blue0;</xsl:text></xsl:if>
	<xsl:if test="(.='Goldenrod') or (.='goldenrod')"><xsl:text>\red218\green165\blue32;</xsl:text></xsl:if>
	<xsl:if test="(.='Gray') or (.='gray')"><xsl:text>\red128\green128\blue128;</xsl:text></xsl:if>
	<xsl:if test="(.='Grey') or (.='grey')"><xsl:text>\red128\green128\blue128;</xsl:text></xsl:if>
	<xsl:if test="(.='Green') or (.='green')"><xsl:text>\red0\green128\blue0;</xsl:text></xsl:if>
	<xsl:if test="(.='GreenYellow') or (.='greenyellow')"><xsl:text>\red173\green255\blue47;</xsl:text></xsl:if>
	<xsl:if test="(.='Honeydew') or (.='honeydew')"><xsl:text>\red240\green255\blue240;</xsl:text></xsl:if>
	<xsl:if test="(.='HotPink') or (.='hotpink')"><xsl:text>\red255\green105\blue180;</xsl:text></xsl:if>
	<xsl:if test="(.='IndianRed') or (.='indianred')"><xsl:text>\red205\green92\blue92;</xsl:text></xsl:if>
	<xsl:if test="(.='Indigo') or (.='indigo')"><xsl:text>\red75\green0\blue130;</xsl:text></xsl:if>
	<xsl:if test="(.='Ivory') or (.='ivory')"><xsl:text>\red255\green255\blue240;</xsl:text></xsl:if>
	<xsl:if test="(.='Khaki') or (.='khaki')"><xsl:text>\red240\green230\blue140;</xsl:text></xsl:if>
	<xsl:if test="(.='Lavender') or (.='lavender')"><xsl:text>\red230\green230\blue250;</xsl:text></xsl:if>
	<xsl:if test="(.='LavenderBlush') or (.='lavenderblush')"><xsl:text>\red255\green240\blue245;</xsl:text></xsl:if>
	<xsl:if test="(.='LawnGreen') or (.='lawngreen')"><xsl:text>\red124\green252\blue0;</xsl:text></xsl:if>
	<xsl:if test="(.='LemonChiffon') or (.='lemonchiffon')"><xsl:text>\red255\green250\blue205;</xsl:text></xsl:if>
	<xsl:if test="(.='LightBlue') or (.='lightblue')"><xsl:text>\red173\green216\blue230;</xsl:text></xsl:if>
	<xsl:if test="(.='LightCoral') or (.='lightcoral')"><xsl:text>\red240\green128\blue128;</xsl:text></xsl:if>
	<xsl:if test="(.='LightCyan') or (.='lightcyan')"><xsl:text>\red224\green255\blue255;</xsl:text></xsl:if>
	<xsl:if test="(.='LightGoldenrodYellow') or (.='lightgoldenrodyellow')"><xsl:text>\red250\green250\blue210;</xsl:text></xsl:if>
	<xsl:if test="(.='LightGreen') or (.='lightgreen')"><xsl:text>\red144\green238\blue144;</xsl:text></xsl:if>
	<xsl:if test="(.='LightGray') or (.='lightgray')"><xsl:text>\red211\green211\blue211;</xsl:text></xsl:if>
	<xsl:if test="(.='LightGrey') or (.='lightgrey')"><xsl:text>\red211\green211\blue211;</xsl:text></xsl:if>
	<xsl:if test="(.='LightPink') or (.='lightpink')"><xsl:text>\red255\green182\blue193;</xsl:text></xsl:if>
	<xsl:if test="(.='LightSalmon') or (.='lightsalmon')"><xsl:text>\red255\green160\blue122;</xsl:text></xsl:if>
	<xsl:if test="(.='LightSeaGreen') or (.='lightseagreen')"><xsl:text>\red32\green178\blue170;</xsl:text></xsl:if>
	<xsl:if test="(.='LightSkyBlue') or (.='lightskyblue')"><xsl:text>\red135\green206\blue250;</xsl:text></xsl:if>
	<xsl:if test="(.='LightSlateGray') or (.='lightslategray')"><xsl:text>\red119\green136\blue153;</xsl:text></xsl:if>
	<xsl:if test="(.='LightSlateGrey') or (.='lightslategrey')"><xsl:text>\red119\green136\blue153;</xsl:text></xsl:if>
	<xsl:if test="(.='LightSteelBlue') or (.='lightsteelblue')"><xsl:text>\red176\green196\blue222;</xsl:text></xsl:if>
	<xsl:if test="(.='LightYellow') or (.='lightyellow')"><xsl:text>\red255\green255\blue224;</xsl:text></xsl:if>
	<xsl:if test="(.='Lime') or (.='lime')"><xsl:text>\red0\green255\blue0;</xsl:text></xsl:if>
	<xsl:if test="(.='LimeGreen') or (.='limegreen')"><xsl:text>\red50\green205\blue50;</xsl:text></xsl:if>
	<xsl:if test="(.='Linen') or (.='linen')"><xsl:text>\red250\green240\blue230;</xsl:text></xsl:if>
	<xsl:if test="(.='Magenta') or (.='magenta')"><xsl:text>\red255\green0\blue255;</xsl:text></xsl:if>
	<xsl:if test="(.='Maroon') or (.='maroon')"><xsl:text>\red128\green0\blue0;</xsl:text></xsl:if>
	<xsl:if test="(.='MediumAquamarine') or (.='mediumaquamarine')"><xsl:text>\red102\green205\blue170;</xsl:text></xsl:if>
	<xsl:if test="(.='MediumBlue') or (.='mediumblue')"><xsl:text>\red0\green0\blue205;</xsl:text></xsl:if>
	<xsl:if test="(.='MediumOrchid') or (.='mediumorchid')"><xsl:text>\red186\green85\blue211;</xsl:text></xsl:if>
	<xsl:if test="(.='MediumPurple') or (.='mediumpurple')"><xsl:text>\red147\green112\blue219;</xsl:text></xsl:if>
	<xsl:if test="(.='MediumSeaGreen') or (.='mediumseagreen')"><xsl:text>\red60\green179\blue113;</xsl:text></xsl:if>
	<xsl:if test="(.='MediumSlateBlue') or (.='mediumslateblue')"><xsl:text>\red123\green104\blue238;</xsl:text></xsl:if>
	<xsl:if test="(.='MediumSpringGreen') or (.='mediumspringgreen')"><xsl:text>\red0\green250\blue154;</xsl:text></xsl:if>
	<xsl:if test="(.='MediumTurquoise') or (.='mediumturquoise')"><xsl:text>\red72\green209\blue204;</xsl:text></xsl:if>
	<xsl:if test="(.='MediumVioletRed') or (.='mediumvioletred')"><xsl:text>\red199\green21\blue133;</xsl:text></xsl:if>
	<xsl:if test="(.='MidnightBlue') or (.='midnightblue')"><xsl:text>\red25\green25\blue112;</xsl:text></xsl:if>
	<xsl:if test="(.='MintCream') or (.='mintcream')"><xsl:text>\red245\green255\blue250;</xsl:text></xsl:if>
	<xsl:if test="(.='MistyRose') or (.='mistyrose')"><xsl:text>\red255\green228\blue225;</xsl:text></xsl:if>
	<xsl:if test="(.='Moccasin') or (.='moccasin')"><xsl:text>\red255\green228\blue181;</xsl:text></xsl:if>
	<xsl:if test="(.='NavajoWhite') or (.='navajowhite')"><xsl:text>\red255\green222\blue173;</xsl:text></xsl:if>
	<xsl:if test="(.='Navy') or (.='navy')"><xsl:text>\red0\green0\blue128;</xsl:text></xsl:if>
	<xsl:if test="(.='OldLace') or (.='oldlace')"><xsl:text>\red253\green245\blue230;</xsl:text></xsl:if>
	<xsl:if test="(.='Olive') or (.='olive')"><xsl:text>\red128\green128\blue0;</xsl:text></xsl:if>
	<xsl:if test="(.='OliveDrab') or (.='olivedrab')"><xsl:text>\red107\green142\blue35;</xsl:text></xsl:if>
	<xsl:if test="(.='Orange') or (.='orange')"><xsl:text>\red255\green165\blue0;</xsl:text></xsl:if>
	<xsl:if test="(.='OrangeRed') or (.='orangered')"><xsl:text>\red255\green69\blue0;</xsl:text></xsl:if>
	<xsl:if test="(.='Orchid') or (.='orchid')"><xsl:text>\red218\green112\blue214;</xsl:text></xsl:if>
	<xsl:if test="(.='PaleGoldenrod') or (.='palegoldenrod')"><xsl:text>\red238\green232\blue170;</xsl:text></xsl:if>
	<xsl:if test="(.='PaleGreen') or (.='palegreen')"><xsl:text>\red152\green251\blue152;</xsl:text></xsl:if>
	<xsl:if test="(.='PaleTurquoise') or (.='paleturquoise')"><xsl:text>\red175\green238\blue238;</xsl:text></xsl:if>
	<xsl:if test="(.='PaleVioletRed') or (.='palevioletred')"><xsl:text>\red219\green112\blue147;</xsl:text></xsl:if>
	<xsl:if test="(.='PapayaWhip') or (.='papayawhip')"><xsl:text>\red255\green239\blue213;</xsl:text></xsl:if>
	<xsl:if test="(.='PeachPuff') or (.='peachpuff')"><xsl:text>\red255\green218\blue185;</xsl:text></xsl:if>
	<xsl:if test="(.='Peru') or (.='peru')"><xsl:text>\red205\green133\blue63;</xsl:text></xsl:if>
	<xsl:if test="(.='Pink') or (.='pink')"><xsl:text>\red255\green192\blue203;</xsl:text></xsl:if>
	<xsl:if test="(.='Plum') or (.='plum')"><xsl:text>\red221\green160\blue221;</xsl:text></xsl:if>
	<xsl:if test="(.='PowderBlue') or (.='powderblue')"><xsl:text>\red176\green224\blue230;</xsl:text></xsl:if>
	<xsl:if test="(.='Purple') or (.='purple')"><xsl:text>\red128\green0\blue128;</xsl:text></xsl:if>
	<xsl:if test="(.='RebeccaPurple') or (.='rebeccapurple')"><xsl:text>\red102\green51\blue153;</xsl:text></xsl:if>
	<xsl:if test="(.='Red') or (.='red')"><xsl:text>\red255\green0\blue0;</xsl:text></xsl:if>
	<xsl:if test="(.='RosyBrown') or (.='rosybrown')"><xsl:text>\red188\green143\blue143;</xsl:text></xsl:if>
	<xsl:if test="(.='RoyalBlue') or (.='royalblue')"><xsl:text>\red65\green105\blue225;</xsl:text></xsl:if>
	<xsl:if test="(.='SaddleBrown') or (.='saddlebrown')"><xsl:text>\red139\green69\blue19;</xsl:text></xsl:if>
	<xsl:if test="(.='Salmon') or (.='salmon')"><xsl:text>\red250\green128\blue114;</xsl:text></xsl:if>
	<xsl:if test="(.='SandyBrown') or (.='sandybrown')"><xsl:text>\red244\green164\blue96;</xsl:text></xsl:if>
	<xsl:if test="(.='SeaGreen') or (.='seagreen')"><xsl:text>\red46\green139\blue87;</xsl:text></xsl:if>
	<xsl:if test="(.='Seashell') or (.='seashell')"><xsl:text>\red255\green245\blue238;</xsl:text></xsl:if>
	<xsl:if test="(.='Sienna') or (.='sienna')"><xsl:text>\red160\green82\blue45;</xsl:text></xsl:if>
	<xsl:if test="(.='Silver') or (.='silver')"><xsl:text>\red192\green192\blue192;</xsl:text></xsl:if>
	<xsl:if test="(.='SkyBlue') or (.='skyblue')"><xsl:text>\red135\green206\blue235;</xsl:text></xsl:if>
	<xsl:if test="(.='SlateBlue') or (.='slateblue')"><xsl:text>\red106\green90\blue205;</xsl:text></xsl:if>
	<xsl:if test="(.='SlateGray') or (.='slategray')"><xsl:text>\red112\green128\blue144;</xsl:text></xsl:if>
	<xsl:if test="(.='SlateGrey') or (.='slategrey')"><xsl:text>\red112\green128\blue144;</xsl:text></xsl:if>
	<xsl:if test="(.='Snow') or (.='snow')"><xsl:text>\red255\green250\blue250;</xsl:text></xsl:if>
	<xsl:if test="(.='SpringGreen') or (.='springgreen')"><xsl:text>\red0\green255\blue127;</xsl:text></xsl:if>
	<xsl:if test="(.='SteelBlue') or (.='steelblue')"><xsl:text>\red70\green130\blue180;</xsl:text></xsl:if>
	<xsl:if test="(.='Tan') or (.='tan')"><xsl:text>\red210\green180\blue140;</xsl:text></xsl:if>
	<xsl:if test="(.='Teal') or (.='teal')"><xsl:text>\red0\green128\blue128;</xsl:text></xsl:if>
	<xsl:if test="(.='Thistle') or (.='thistle')"><xsl:text>\red216\green191\blue216;</xsl:text></xsl:if>
	<xsl:if test="(.='Tomato') or (.='tomato')"><xsl:text>\red255\green99\blue71;</xsl:text></xsl:if>
	<xsl:if test="(.='Turquoise') or (.='turquoise')"><xsl:text>\red64\green224\blue208;</xsl:text></xsl:if>
	<xsl:if test="(.='Violet') or (.='violet')"><xsl:text>\red238\green130\blue238;</xsl:text></xsl:if>
	<xsl:if test="(.='Wheat') or (.='wheat')"><xsl:text>\red245\green222\blue179;</xsl:text></xsl:if>
	<xsl:if test="(.='White') or (.='white')"><xsl:text>\red255\green255\blue255;</xsl:text></xsl:if>
	<xsl:if test="(.='WhiteSmoke') or (.='whitesmoke')"><xsl:text>\red245\green245\blue245;</xsl:text></xsl:if>
	<xsl:if test="(.='Yellow') or (.='yellow')"><xsl:text>\red255\green255\blue0;</xsl:text></xsl:if>
	<xsl:if test="(.='YellowGreen') or (.='yellowgreen')"><xsl:text>\red154\green205\blue50;</xsl:text></xsl:if>
      </xsl:for-each>
      <xsl:text>}</xsl:text>
    </xsl:if>

    <xsl:apply-templates />

    <xsl:text>}}</xsl:text>

  </xsl:template>
  
  <xsl:template match="i">{\i <xsl:apply-templates />\i0}</xsl:template>
  <xsl:template match="b">{\b <xsl:apply-templates />\b0}</xsl:template>
  <xsl:template match="ul">{\ul <xsl:apply-templates />\ul0}</xsl:template>
  <xsl:template match="strike">{\strike <xsl:apply-templates />\strike0}</xsl:template>
  <xsl:template match="caps">{\caps <xsl:apply-templates />\caps0}</xsl:template>
  <xsl:template match="smallcaps">{\scaps <xsl:apply-templates />\scaps0}</xsl:template>
  <xsl:template match="outline">{\outl <xsl:apply-templates />\outl0}</xsl:template>

  <xsl:template match="font">
    <xsl:text>{</xsl:text>
    <xsl:if test="./@face!=''">
      <xsl:text>\f</xsl:text>
      <xsl:variable name="facename">
	<xsl:value-of select="./@face" />
      </xsl:variable>
      <xsl:for-each select="$faces">
	<xsl:if test=".=$facename">
	  <xsl:value-of select="position()" />
	</xsl:if>
      </xsl:for-each>
    </xsl:if>

    <xsl:if test="./@color!=''">
      <xsl:text>\cf</xsl:text>
      <xsl:variable name="colorname">
	<xsl:value-of select="./@color" />
      </xsl:variable>
      <xsl:for-each select="$colors">
	<xsl:if test=".=$colorname">
	  <xsl:value-of select="position()" />
	</xsl:if>
      </xsl:for-each>
    </xsl:if>

    <xsl:if test="./@size!=''">
      <xsl:text>\fs</xsl:text>
      <xsl:value-of select="(./@size)*2" />
    </xsl:if>

    <xsl:text> </xsl:text>
    <xsl:apply-templates />

    <xsl:if test="./@face!=''">
      <xsl:text>\f0</xsl:text>
    </xsl:if>
    <xsl:if test="./@color!=''">
      <xsl:text>\cf0</xsl:text>
    </xsl:if>
    <xsl:text>}</xsl:text>

  </xsl:template>

  <xsl:template match="p">
    <xsl:text>{\par\pard</xsl:text>
    <xsl:if test="./@align='left'"><xsl:text>\ql</xsl:text></xsl:if>
    <xsl:if test="./@align='right'"><xsl:text>\qr</xsl:text></xsl:if>
    <xsl:if test="(./@align='justified') or (./@align='justify')"><xsl:text>\qj</xsl:text></xsl:if>
    <xsl:if test="(./@align='centered') or (./@align='center')"><xsl:text>\qc</xsl:text></xsl:if>
    <xsl:text> </xsl:text>
    <xsl:apply-templates />
    <xsl:text>}</xsl:text>
  </xsl:template>
  
</xsl:stylesheet>
