
"""
Python program that reads and parses currency.xml and translates
it into currency.rml.

USAGE: there are no arguments

   > python currency.py

to simplify the demonstration the filenames are hardcoded
at the top of the file as INPUTFILE and OUTPUTFILE.  The output
of the program "currency.rml" must be processed by the rml2pdf
program to generate the final PDF output "currency.pdf".

This program demonstrates a simple method for converting an XML file which
contains a sequence of records into an RML file appropriate for translation
into a PDF file.  The output file formats the data in a tabular format on
multiple pages with table breaks for each month and year change.  Outline
entries are also introduced whenever a year or month changes.

The input file contains a top level tag "history" which in turn contains
a number of "CanadianDollarConversion" tags which have attributes but contain
no other tags.  For example:

<?xml version="1.0" encoding="iso-8859-1" standalone="no" ?>
<!DOCTYPE history SYSTEM "currency.dtd">

<history>

 <CanadianDollarConversion
    YYYYMMDD="1980/01/02"
    DayOfWeek="Wed"
    USDollar="0.85780"
    Euro=""
    DeutcheMark="1.4698"
    FrenchFranc="3.4440"
    JapaneseYen="204.54"
    BritishPound="0.38250"
    SwissFranc="1.3531"
    AustralianDollar=""
    HongKongDollar=""
    NewZealandDollar=""
/>

 <CanadianDollarConversion
    YYYYMMDD="1980/01/03"
    DayOfWeek="Thu"
    USDollar="0.85450"
    Euro=""
    DeutcheMark="1.4618"
    FrenchFranc="3.4265"
    JapaneseYen="203.67"
    BritishPound="0.38150"
    SwissFranc="1.3432"
    AustralianDollar=""
    HongKongDollar=""
    NewZealandDollar=""
/>
...</history>

"""

INPUTFILE = "currency.xml"
OUTPUTFILE = "currency.rml"

# this is the top of the RML output which describes the document styles
# and page layouts.

RMLHEADER = """<?xml version="1.0" encoding="iso-8859-1" standalone="no" ?> 
<!DOCTYPE document SYSTEM "rml_1_0.dtd"> 
<document filename="currency.pdf" > 

<template  pageSize="(8.5in, 11in)">
 <pageTemplate id="main">
	<pageGraphics>
 <!-- headers and page numbers on each page -->
	<setFont name="Helvetica-Bold" size="10"/>
        <drawCentredString x="4.25in" y="0.5in">Page <pageNumber/> (source: Univ. of British Columbia)</drawCentredString>
        <drawCentredString x="4.25in" y="10.7in">Canadian Dollar Historical Conversions</drawCentredString>
        
            <translate dy="10.1in" dx="1.75in"/>
            <rotate degrees="25"/>
            <drawString x="0" y="0">YYYYMMDD</drawString>
            <rotate degrees="-25"/><translate dy="0" dx="0.5in"/><rotate degrees="25"/>
            <drawString x="0" y="0">Day of Week</drawString>
            <rotate degrees="-25"/><translate dy="0" dx="0.5in"/><rotate degrees="25"/>
            <drawString x="0" y="0">US Dollar</drawString>
            <rotate degrees="-25"/><translate dy="0" dx="0.5in"/><rotate degrees="25"/>
            <drawString x="0" y="0">Euro</drawString>
            <rotate degrees="-25"/><translate dy="0" dx="0.5in"/><rotate degrees="25"/>
            <drawString x="0" y="0">Deutche Mark</drawString>
            <rotate degrees="-25"/><translate dy="0" dx="0.5in"/><rotate degrees="25"/>
            <drawString x="0" y="0">French Franc</drawString>
            <rotate degrees="-25"/><translate dy="0" dx="0.5in"/><rotate degrees="25"/>
            <drawString x="0" y="0">Japanese Yen</drawString>
            <rotate degrees="-25"/><translate dy="0" dx="0.5in"/><rotate degrees="25"/>
            <drawString x="0" y="0">British Pound</drawString>
            <rotate degrees="-25"/><translate dy="0" dx="0.5in"/><rotate degrees="25"/>
            <drawString x="0" y="0">Swiss Franc</drawString>
            <rotate degrees="-25"/><translate dy="0" dx="0.5in"/><rotate degrees="25"/>
            <drawString x="0" y="0">Australian Dollar</drawString>
            <rotate degrees="-25"/><translate dy="0" dx="0.5in"/><rotate degrees="25"/>
            <drawString x="0" y="0">New Zealand Dollar</drawString>
            
        </pageGraphics>
   <frame id="first" x1="1in" y1="1in" width="6.5in" height="9in"/> 
 </pageTemplate>
</template>

<stylesheet>
	<blockTableStyle id="mystyle">
		<blockBackground colorName="lemonchiffon"/>
		<lineStyle kind="GRID" colorName="crimson" />
		<blockFont name="Times-Roman" size="6"/>
		<blockFont name="Helvetica" size="8" start="1,0"/>
		<blockAlignment value="Center"/>
	</blockTableStyle>
</stylesheet>

<story>

"""

# this is a convenience variable
STARTTABLE = """
<blockTable style="mystyle" colWidths="0.5in,0.5in,0.5in,0.5in,0.5in,0.5in,0.5in,0.5in,0.5in,0.5in,0.5in">
"""

# this is an example body, used for testing the stylistic elements without parsing the XML
EXAMPLEBODY="""
<blockTable style="mystyle" colWidths="0.5in,0.5in,0.5in,0.5in,0.5in,0.5in,0.5in,0.5in,0.5in,0.5in,0.5in">
<tr>
<td> xxx </td>
<td> xxx </td>
<td> xxx </td>
<td> xxx </td>
<td> xxx </td>
<td> xxx </td>
<td> xxx </td>
<td> xxx </td>
<td> xxx </td>
<td> xxx </td>
<td> xxx </td>
</tr>
</blockTable>
"""

# this is text that must be placed at the end of the RML file
RMLTRAILER="""
</story>

</document>"""

def makeTestSample():
    "this function just makes a test file to check the formatting"
    f = open('test.rml', "w")
    f.write(RMLHEADER)
    f.write(EXAMPLEBODY)
    f.write(RMLTRAILER)
    print "wrote test.rml"

def currency2rml(inputfilename, outputfilename):
    "translate input XML in inputfilename to output RML in outputfilename"
    from reportlab.lib import rparsexml
    
    # get the text of the input xml as a string
    inputtext = open(inputfilename).read()
    
    # open the output file
    outputfile = open(outputfilename, "w")
    
    # write the prolog in the output file
    outputfile.write(RMLHEADER)
    
    # parse the xml text into a tree-like data structure
    parsedtext = rparsexml.parsexml(inputtext)
    
    # discard dummy top node of tree
    (name, dictofattributes, contentlist, miscellaneousinfo) = parsedtext
    if len(contentlist)!=1:
        raise ValueError, "too much content %s" % len(contentlist)
    topleveltag = contentlist[0]
    
    # extract name and children of top level tag
    (name, dictofattributes, contentlist, miscellaneousinfo) = topleveltag
    if name!="history":
        raise ValueError, "bad top level tag %s" % name
    
    # now iterate through the leaves of the one level xml tree
    from types import TupleType, StringType
    import string
    lastyear = lastmonth = None
    for element in contentlist:
        # some elements will be strings of whitespace between tags: ignore them
        if type(element) is StringType:
            pass
        
        elif type(element) is TupleType:
            # extract the information from this entry
            (name, dictofattributes, dummy, miscellaneousinfo) = element
            
            ######## THIS SECTION DEALS WITH PLACING THE OUTLINE ENTRY TAGS
            
            # OUTLINE ENTRIES: WHENEVER THE YEAR CHANGES ADD A LEVEL 0 OUTLINE ENTRY
            yyyymmdd = dictofattributes["YYYYMMDD"]
            [yyyy, mm, dd] = string.split(string.strip(yyyymmdd), "/")
            if yyyy!=lastyear:
                outputfile.write("\n\n<h2>Year %s</h2>\n\n" % yyyy)
                outputfile.write('<outlineAdd level="0">%s</outlineAdd>\n' % yyyy)
                
            # WHENEVER THE MONTH CHANGES ADD A LEVEL 1 OUTLINE ENTRY
            if mm!=lastmonth:
                outputfile.write("\n\n<para>Month %s/%s</para>\n\n" % (mm,yyyy))
                outputfile.write('<outlineAdd level="1">%s/%s</outlineAdd>\n' % (mm,yyyy))
            (lastyear, lastmonth) = (yyyy, mm)

            ####### THIS SECTION DEALS WITH PLACING THE TABLE ROWS
            
            # uncomment this line to see progress and dictionary content
            #print dictofattributes
            # print out a table row for this entry
            outputfile.write(STARTTABLE)
            outputfile.write("<tr>\n")
            for attributename in ["YYYYMMDD", "DayOfWeek",
                                 "USDollar", "Euro", "DeutcheMark", "FrenchFranc", "JapaneseYen",
                                 "BritishPound", "SwissFranc", "AustralianDollar",
                                 "NewZealandDollar"]:
                value = dictofattributes[attributename]
                outputfile.write(" <td>%s</td>" % value)
            outputfile.write("\n</tr></blockTable>\n")
            
        else: # sanity check
            raise ValueError, "unexpected content element type %s" % type(element)

    # write the trailer
    outputfile.write(RMLTRAILER)
    outputfile.close()
    print "wrote", outputfilename

if __name__=="__main__":
    print "making test sample"
    makeTestSample()
    print "now translating", INPUTFILE, "to", OUTPUTFILE
    currency2rml(INPUTFILE, OUTPUTFILE)
    
