ODFPY  1.2.0
odf2xhtml.py
Go to the documentation of this file.
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3 # Copyright (C) 2006-2010 Søren Roug, European Environment Agency
4 #
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2.1 of the License, or (at your option) any later version.
9 #
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # Lesser General Public License for more details.
14 #
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 #
19 # Contributor(s):
20 #
21 #import pdb
22 #pdb.set_trace()
23 
24 import sys, os.path
25 sys.path.append(os.path.dirname(__file__))
26 from xml.sax import handler
27 from xml.sax.saxutils import escape, quoteattr
28 from xml.dom import Node
29 
30 from opendocument import load
31 
32 from namespaces import ANIMNS, CHARTNS, CONFIGNS, DCNS, DR3DNS, DRAWNS, FONS, \
33  FORMNS, MATHNS, METANS, NUMBERNS, OFFICENS, PRESENTATIONNS, SCRIPTNS, \
34  SMILNS, STYLENS, SVGNS, TABLENS, TEXTNS, XLINKNS
35 
36 # Handling of styles
37 #
38 # First there are font face declarations. These set up a font style that will be
39 # referenced from a text-property. The declaration describes the font making
40 # it possible for the application to find a similar font should the system not
41 # have that particular one. The StyleToCSS stores these attributes to be used
42 # for the CSS2 font declaration.
43 #
44 # Then there are default-styles. These set defaults for various style types:
45 # "text", "paragraph", "section", "ruby", "table", "table-column", "table-row",
46 # "table-cell", "graphic", "presentation", "drawing-page", "chart".
47 # Since CSS2 can't refer to another style, ODF2XHTML add these to all
48 # styles unless overridden.
49 #
50 # The real styles are declared in the <style:style> element. They have a
51 # family referring to the default-styles, and may have a parent style.
52 #
53 # Styles have scope. The same name can be used for both paragraph and
54 # character etc. styles Since CSS2 has no scope we use a prefix. (Not elegant)
55 # In ODF a style can have a parent, these parents can be chained.
56 
57 
62 class StyleToCSS:
63 
64  def __init__(self):
65  # Font declarations
66  self.fontdict = {}
67 
68  # Fill-images from presentations for backgrounds
69  self.fillimages = {}
70 
71  self.ruleconversions = {
72  (DRAWNS,u'fill-image-name'): self.c_drawfillimage,
73  (FONS,u"background-color"): self.c_fo,
74  (FONS,u"border"): self.c_fo,
75  (FONS,u"border-bottom"): self.c_fo,
76  (FONS,u"border-left"): self.c_fo,
77  (FONS,u"border-right"): self.c_fo,
78  (FONS,u"border-top"): self.c_fo,
79  (FONS,u"color"): self.c_fo,
80  (FONS,u"font-family"): self.c_fo,
81  (FONS,u"font-size"): self.c_fo,
82  (FONS,u"font-style"): self.c_fo,
83  (FONS,u"font-variant"): self.c_fo,
84  (FONS,u"font-weight"): self.c_fo,
85  (FONS,u"line-height"): self.c_fo,
86  (FONS,u"margin"): self.c_fo,
87  (FONS,u"margin-bottom"): self.c_fo,
88  (FONS,u"margin-left"): self.c_fo,
89  (FONS,u"margin-right"): self.c_fo,
90  (FONS,u"margin-top"): self.c_fo,
91  (FONS,u"min-height"): self.c_fo,
92  (FONS,u"padding"): self.c_fo,
93  (FONS,u"padding-bottom"): self.c_fo,
94  (FONS,u"padding-left"): self.c_fo,
95  (FONS,u"padding-right"): self.c_fo,
96  (FONS,u"padding-top"): self.c_fo,
97  (FONS,u"page-width"): self.c_page_width,
98  (FONS,u"page-height"): self.c_page_height,
99  (FONS,u"text-align"): self.c_text_align,
100  (FONS,u"text-indent") :self.c_fo,
101  (TABLENS,u'border-model') :self.c_border_model,
102  (STYLENS,u'column-width') : self.c_width,
103  (STYLENS,u"font-name"): self.c_fn,
104  (STYLENS,u'horizontal-pos'): self.c_hp,
105  (STYLENS,u'text-position'): self.c_text_position,
106  (STYLENS,u'text-line-through-style'): self.c_text_line_through_style,
107  (STYLENS,u'text-underline-style'): self.c_text_underline_style,
108  (STYLENS,u'width') : self.c_width,
109  # FIXME Should do style:vertical-pos here
110  }
111 
112 
120  def save_font(self, name, family, generic):
121  htmlgeneric = "sans-serif"
122  if generic == "roman": htmlgeneric = "serif"
123  elif generic == "swiss": htmlgeneric = "sans-serif"
124  elif generic == "modern": htmlgeneric = "monospace"
125  elif generic == "decorative": htmlgeneric = "sans-serif"
126  elif generic == "script": htmlgeneric = "monospace"
127  elif generic == "system": htmlgeneric = "serif"
128  self.fontdict[name] = (family, htmlgeneric)
129 
130 
135  def c_drawfillimage(self, ruleset, sdict, rule, val):
136  sdict['background-image'] = "url('%s')" % self.fillimages[val]
137 
138 
140  def c_fo(self, ruleset, sdict, rule, val):
141  selector = rule[1]
142  sdict[selector] = val
143 
144 
146  def c_border_model(self, ruleset, sdict, rule, val):
147  if val == 'collapsing':
148  sdict['border-collapse'] ='collapse'
149  else:
150  sdict['border-collapse'] ='separate'
151 
152 
154  def c_width(self, ruleset, sdict, rule, val):
155  sdict['width'] = val
156 
157 
159  def c_text_align(self, ruleset, sdict, rule, align):
160  if align == "start": align = "left"
161  if align == "end": align = "right"
162  sdict['text-align'] = align
163 
164 
169  def c_fn(self, ruleset, sdict, rule, fontstyle):
170  generic = ruleset.get((STYLENS,'font-family-generic') )
171  if generic is not None:
172  self.save_font(fontstyle, fontstyle, generic)
173  family, htmlgeneric = self.fontdict.get(fontstyle, (fontstyle, 'serif'))
174  sdict['font-family'] = '%s, %s' % (family, htmlgeneric)
175 
176 
195  def c_text_position(self, ruleset, sdict, rule, tp):
196  textpos = tp.split(' ')
197  if len(textpos) == 2 and textpos[0] != "0%":
198  # Bug in OpenOffice. If vertical-align is 0% - ignore the text size.
199  sdict['font-size'] = textpos[1]
200  if textpos[0] == "super":
201  sdict['vertical-align'] = "33%"
202  elif textpos[0] == "sub":
203  sdict['vertical-align'] = "-33%"
204  else:
205  sdict['vertical-align'] = textpos[0]
206 
207  def c_hp(self, ruleset, sdict, rule, hpos):
208  #FIXME: Frames wrap-style defaults to 'parallel', graphics to 'none'.
209  # It is properly set in the parent-styles, but the program doesn't
210  # collect the information.
211  wrap = ruleset.get((STYLENS,'wrap'),'parallel')
212  # Can have: from-left, left, center, right, from-inside, inside, outside
213  if hpos == "center":
214  sdict['margin-left'] = "auto"
215  sdict['margin-right'] = "auto"
216 # else:
217 # # force it to be *something* then delete it
218 # sdict['margin-left'] = sdict['margin-right'] = ''
219 # del sdict['margin-left'], sdict['margin-right']
220 
221  if hpos in ("right","outside"):
222  if wrap in ( "left", "parallel","dynamic"):
223  sdict['float'] = "right"
224  elif wrap == "run-through":
225  sdict['position'] = "absolute" # Simulate run-through
226  sdict['top'] = "0"
227  sdict['right'] = "0";
228  else: # No wrapping
229  sdict['margin-left'] = "auto"
230  sdict['margin-right'] = "0cm"
231  elif hpos in ("left", "inside"):
232  if wrap in ( "right", "parallel","dynamic"):
233  sdict['float'] = "left"
234  elif wrap == "run-through":
235  sdict['position'] = "absolute" # Simulate run-through
236  sdict['top'] = "0"
237  sdict['left'] = "0"
238  else: # No wrapping
239  sdict['margin-left'] = "0cm"
240  sdict['margin-right'] = "auto"
241  elif hpos in ("from-left", "from-inside"):
242  if wrap in ( "right", "parallel"):
243  sdict['float'] = "left"
244  else:
245  sdict['position'] = "relative" # No wrapping
246  if (SVGNS,'x') in ruleset:
247  sdict['left'] = ruleset[(SVGNS,'x')]
248 
249 
253  def c_page_width(self, ruleset, sdict, rule, val):
254  sdict['width'] = val
255 
256 
260  def c_text_underline_style(self, ruleset, sdict, rule, val):
261  if val and val != "none":
262  sdict['text-decoration'] = "underline"
263 
264 
268  def c_text_line_through_style(self, ruleset, sdict, rule, val):
269  if val and val != "none":
270  sdict['text-decoration'] = "line-through"
271 
272 
274  def c_page_height(self, ruleset, sdict, rule, val):
275  sdict['height'] = val
276 
277 
281  def convert_styles(self, ruleset):
282  sdict = {}
283  procedures=[]
284  for rule,val in ruleset.items():
285  if rule[0] == '':
286  sdict[rule[1]] = val
287  continue
288  method = self.ruleconversions.get(rule, None )
289  if method:
290  procedures.append([method, ruleset, sdict, rule, val])
291  # this ensures that the procedures for horizontal position
292  # are run last! It is important since Python3 makes the order
293  # of dictionaries unpredictable
294  for p in filter(lambda x: x[0] != self.c_hp, procedures):
295  method, ruleset, sdict, rule, val = p
296  method(ruleset, sdict, rule, val)
297  for p in filter(lambda x: x[0] == self.c_hp, procedures):
298  method, ruleset, sdict, rule, val = p
299  method(ruleset, sdict, rule, val)
300 
301  return sdict
302 
303 
304 class TagStack:
305  def __init__(self):
306  self.stack = []
307 
308  def push(self, tag, attrs):
309  self.stack.append( (tag, attrs) )
310 
311  def pop(self):
312  item = self.stack.pop()
313  return item
314 
315  def stackparent(self):
316  item = self.stack[-1]
317  return item[1]
318 
319 
321  def rfindattr(self, attr):
322  for tag, attrs in self.stack:
323  if attr in attrs:
324  return attrs[attr]
325  return None
326  def count_tags(self, tag):
327  c = 0
328  for ttag, tattrs in self.stack:
329  if ttag == tag: c = c + 1
330  return c
331 
332 special_styles = {
333  'S-Emphasis':'em',
334  'S-Citation':'cite',
335  'S-Strong_20_Emphasis':'strong',
336  'S-Variable':'var',
337  'S-Definition':'dfn',
338  'S-Teletype':'tt',
339  'P-Heading_20_1':'h1',
340  'P-Heading_20_2':'h2',
341  'P-Heading_20_3':'h3',
342  'P-Heading_20_4':'h4',
343  'P-Heading_20_5':'h5',
344  'P-Heading_20_6':'h6',
345 # 'P-Caption':'caption',
346  'P-Addressee':'address',
347 # 'P-List_20_Heading':'dt',
348 # 'P-List_20_Contents':'dd',
349  'P-Preformatted_20_Text':'pre',
350 # 'P-Table_20_Heading':'th',
351 # 'P-Table_20_Contents':'td',
352 # 'P-Text_20_body':'p'
353 }
354 
355 #-----------------------------------------------------------------------------
356 #
357 # ODFCONTENTHANDLER
358 #
359 #-----------------------------------------------------------------------------
360 
362 class ODF2XHTML(handler.ContentHandler):
363 
364  def __init__(self, generate_css=True, embedable=False):
365  # Tags
366  self.generate_css = generate_css
367  self.elements = {
368  (DCNS, 'title'): (self.s_processcont, self.e_dc_title),
369  (DCNS, 'language'): (self.s_processcont, self.e_dc_contentlanguage),
370  (DCNS, 'creator'): (self.s_processcont, self.e_dc_creator),
371  (DCNS, 'description'): (self.s_processcont, self.e_dc_metatag),
372  (DCNS, 'date'): (self.s_processcont, self.e_dc_metatag),
373  (DRAWNS, 'custom-shape'): (self.s_custom_shape, self.e_custom_shape),
374  (DRAWNS, 'frame'): (self.s_draw_frame, self.e_draw_frame),
375  (DRAWNS, 'image'): (self.s_draw_image, None),
376  (DRAWNS, 'fill-image'): (self.s_draw_fill_image, None),
377  (DRAWNS, "layer-set"):(self.s_ignorexml, None),
378  (DRAWNS, 'object'): (self.s_draw_object, None),
379  (DRAWNS, 'object-ole'): (self.s_draw_object_ole, None),
380  (DRAWNS, 'page'): (self.s_draw_page, self.e_draw_page),
381  (DRAWNS, 'text-box'): (self.s_draw_textbox, self.e_draw_textbox),
382  (METANS, 'creation-date'):(self.s_processcont, self.e_dc_metatag),
383  (METANS, 'generator'):(self.s_processcont, self.e_dc_metatag),
384  (METANS, 'initial-creator'): (self.s_processcont, self.e_dc_metatag),
385  (METANS, 'keyword'): (self.s_processcont, self.e_dc_metatag),
386  (NUMBERNS, "boolean-style"):(self.s_ignorexml, None),
387  (NUMBERNS, "currency-style"):(self.s_ignorexml, None),
388  (NUMBERNS, "date-style"):(self.s_ignorexml, None),
389  (NUMBERNS, "number-style"):(self.s_ignorexml, None),
390  (NUMBERNS, "text-style"):(self.s_ignorexml, None),
391  (OFFICENS, "annotation"):(self.s_ignorexml, None),
392  (OFFICENS, "automatic-styles"):(self.s_office_automatic_styles, None),
393  (OFFICENS, "document"):(self.s_office_document_content, self.e_office_document_content),
394  (OFFICENS, "document-content"):(self.s_office_document_content, self.e_office_document_content),
395  (OFFICENS, "forms"):(self.s_ignorexml, None),
396  (OFFICENS, "master-styles"):(self.s_office_master_styles, None),
397  (OFFICENS, "meta"):(self.s_ignorecont, None),
398  (OFFICENS, "presentation"):(self.s_office_presentation, self.e_office_presentation),
399  (OFFICENS, "spreadsheet"):(self.s_office_spreadsheet, self.e_office_spreadsheet),
400  (OFFICENS, "styles"):(self.s_office_styles, None),
401  (OFFICENS, "text"):(self.s_office_text, self.e_office_text),
402  (OFFICENS, "scripts"):(self.s_ignorexml, None),
403  (OFFICENS, "settings"):(self.s_ignorexml, None),
404  (PRESENTATIONNS, "notes"):(self.s_ignorexml, None),
405 # (STYLENS, "default-page-layout"):(self.s_style_default_page_layout, self.e_style_page_layout),
406  (STYLENS, "default-page-layout"):(self.s_ignorexml, None),
407  (STYLENS, "default-style"):(self.s_style_default_style, self.e_style_default_style),
408  (STYLENS, "drawing-page-properties"):(self.s_style_handle_properties, None),
409  (STYLENS, "font-face"):(self.s_style_font_face, None),
410 # (STYLENS, "footer"):(self.s_style_footer, self.e_style_footer),
411 # (STYLENS, "footer-style"):(self.s_style_footer_style, None),
412  (STYLENS, "graphic-properties"):(self.s_style_handle_properties, None),
413  (STYLENS, "handout-master"):(self.s_ignorexml, None),
414 # (STYLENS, "header"):(self.s_style_header, self.e_style_header),
415 # (STYLENS, "header-footer-properties"):(self.s_style_handle_properties, None),
416 # (STYLENS, "header-style"):(self.s_style_header_style, None),
417  (STYLENS, "master-page"):(self.s_style_master_page, None),
418  (STYLENS, "page-layout-properties"):(self.s_style_handle_properties, None),
419  (STYLENS, "page-layout"):(self.s_style_page_layout, self.e_style_page_layout),
420 # (STYLENS, "page-layout"):(self.s_ignorexml, None),
421  (STYLENS, "paragraph-properties"):(self.s_style_handle_properties, None),
422  (STYLENS, "style"):(self.s_style_style, self.e_style_style),
423  (STYLENS, "table-cell-properties"):(self.s_style_handle_properties, None),
424  (STYLENS, "table-column-properties"):(self.s_style_handle_properties, None),
425  (STYLENS, "table-properties"):(self.s_style_handle_properties, None),
426  (STYLENS, "text-properties"):(self.s_style_handle_properties, None),
427  (SVGNS, 'desc'): (self.s_ignorexml, None),
428  (TABLENS, 'covered-table-cell'): (self.s_ignorexml, None),
429  (TABLENS, 'table-cell'): (self.s_table_table_cell, self.e_table_table_cell),
430  (TABLENS, 'table-column'): (self.s_table_table_column, None),
431  (TABLENS, 'table-row'): (self.s_table_table_row, self.e_table_table_row),
432  (TABLENS, 'table'): (self.s_table_table, self.e_table_table),
433  (TEXTNS, 'a'): (self.s_text_a, self.e_text_a),
434  (TEXTNS, "alphabetical-index-source"):(self.s_text_x_source, self.e_text_x_source),
435  (TEXTNS, "bibliography-configuration"):(self.s_ignorexml, None),
436  (TEXTNS, "bibliography-source"):(self.s_text_x_source, self.e_text_x_source),
437  (TEXTNS, 'bookmark'): (self.s_text_bookmark, None),
438  (TEXTNS, 'bookmark-start'): (self.s_text_bookmark, None),
439  (TEXTNS, 'bookmark-ref'): (self.s_text_bookmark_ref, self.e_text_a),
440  (TEXTNS, 'bookmark-ref-start'): (self.s_text_bookmark_ref, None),
441  (TEXTNS, 'h'): (self.s_text_h, self.e_text_h),
442  (TEXTNS, "illustration-index-source"):(self.s_text_x_source, self.e_text_x_source),
443  (TEXTNS, 'line-break'):(self.s_text_line_break, None),
444  (TEXTNS, "linenumbering-configuration"):(self.s_ignorexml, None),
445  (TEXTNS, "list"):(self.s_text_list, self.e_text_list),
446  (TEXTNS, "list-item"):(self.s_text_list_item, self.e_text_list_item),
447  (TEXTNS, "list-level-style-bullet"):(self.s_text_list_level_style_bullet, self.e_text_list_level_style_bullet),
448  (TEXTNS, "list-level-style-number"):(self.s_text_list_level_style_number, self.e_text_list_level_style_number),
449  (TEXTNS, "list-style"):(None, None),
450  (TEXTNS, "note"):(self.s_text_note, None),
451  (TEXTNS, "note-body"):(self.s_text_note_body, self.e_text_note_body),
452  (TEXTNS, "note-citation"):(None, self.e_text_note_citation),
453  (TEXTNS, "notes-configuration"):(self.s_ignorexml, None),
454  (TEXTNS, "object-index-source"):(self.s_text_x_source, self.e_text_x_source),
455  (TEXTNS, 'p'): (self.s_text_p, self.e_text_p),
456  (TEXTNS, 's'): (self.s_text_s, None),
457  (TEXTNS, 'span'): (self.s_text_span, self.e_text_span),
458  (TEXTNS, 'tab'): (self.s_text_tab, None),
459  (TEXTNS, "table-index-source"):(self.s_text_x_source, self.e_text_x_source),
460  (TEXTNS, "table-of-content-source"):(self.s_text_x_source, self.e_text_x_source),
461  (TEXTNS, "user-index-source"):(self.s_text_x_source, self.e_text_x_source),
462  }
463  if embedable:
464  self.set_embedable()
465  self._resetobject()
466 
467 
469  def set_plain(self):
470  self.generate_css = False
471 
472 
474  def set_embedable(self):
475  self.elements[(OFFICENS, u"text")] = (None,None)
476  self.elements[(OFFICENS, u"spreadsheet")] = (None,None)
477  self.elements[(OFFICENS, u"presentation")] = (None,None)
478  self.elements[(OFFICENS, u"document-content")] = (None,None)
479 
480 
481 
485  def add_style_file(self, stylefilename, media=None):
486  self.use_internal_css = False
487  self.stylefilename = stylefilename
488  if media:
489  self.metatags.append('<link rel="stylesheet" type="text/css" href="%s" media="%s"/>\n' % (stylefilename,media))
490  else:
491  self.metatags.append('<link rel="stylesheet" type="text/css" href="%s"/>\n' % (stylefilename))
492 
493  def _resetfootnotes(self):
494  # Footnotes and endnotes
495  self.notedict = {}
496  self.currentnote = 0
497  self.notebody = ''
498 
499  def _resetobject(self):
500  self.lines = []
501  self._wfunc = self._wlines
502  self.xmlfile = ''
503  self.title = ''
504  self.language = ''
505  self.creator = ''
506  self.data = []
508  self.htmlstack = []
509  self.pstack = []
510  self.processelem = True
511  self.processcont = True
512  self.listtypes = {}
513  self.headinglevels = [0, 0,0,0,0,0, 0,0,0,0,0] # level 0 to 10
514  self.use_internal_css = True
515  self.cs = StyleToCSS()
516  self.anchors = {}
517 
518  # Style declarations
519  self.stylestack = []
520  self.styledict = {}
521  self.currentstyle = None
522 
523  self._resetfootnotes()
524 
525  # Tags from meta.xml
526  self.metatags = []
527 
528 
529  def writeout(self, s):
530  if s != '':
531  self._wfunc(s)
532 
533  def writedata(self):
534  d = ''.join(self.data)
535  if d != '':
536  self.writeout(escape(d))
537 
538 
540  def opentag(self, tag, attrs={}, block=False):
541  self.htmlstack.append((tag,attrs,block))
542  a = []
543  for key,val in attrs.items():
544  a.append('''%s=%s''' % (key, quoteattr(val)))
545  if len(a) == 0:
546  self.writeout("<%s>" % tag)
547  else:
548  self.writeout("<%s %s>" % (tag, " ".join(a)))
549  if block == True:
550  self.writeout("\n")
551 
552 
554  def closetag(self, tag, block=True):
555  self.htmlstack.pop()
556  self.writeout("</%s>" % tag)
557  if block == True:
558  self.writeout("\n")
559 
560  def emptytag(self, tag, attrs={}):
561  a = []
562  for key,val in attrs.items():
563  a.append('''%s=%s''' % (key, quoteattr(val)))
564  self.writeout("<%s %s/>\n" % (tag, " ".join(a)))
565 
566 #--------------------------------------------------
567 # Interface to parser
568 #--------------------------------------------------
569  def characters(self, data):
570  if self.processelem and self.processcont:
571  self.data.append(data)
572 
573  def startElementNS(self, tag, qname, attrs):
574  self.pstack.append( (self.processelem, self.processcont) )
575  if self.processelem:
576  method = self.elements.get(tag, (None, None) )[0]
577  if method:
578  self.handle_starttag(tag, method, attrs)
579  else:
580  self.unknown_starttag(tag,attrs)
581  self.tagstack.push( tag, attrs )
582 
583  def endElementNS(self, tag, qname):
584  stag, attrs = self.tagstack.pop()
585  if self.processelem:
586  method = self.elements.get(tag, (None, None) )[1]
587  if method:
588  self.handle_endtag(tag, attrs, method)
589  else:
590  self.unknown_endtag(tag, attrs)
591  self.processelem, self.processcont = self.pstack.pop()
592 
593 #--------------------------------------------------
594  def handle_starttag(self, tag, method, attrs):
595  method(tag,attrs)
596 
597  def handle_endtag(self, tag, attrs, method):
598  method(tag, attrs)
599 
600  def unknown_starttag(self, tag, attrs):
601  pass
602 
603  def unknown_endtag(self, tag, attrs):
604  pass
605 
606 
610  def s_ignorexml(self, tag, attrs):
611  self.processelem = False
612 
613 
615  def s_ignorecont(self, tag, attrs):
616  self.processcont = False
617 
618 
620  def s_processcont(self, tag, attrs):
621  self.processcont = True
622 
623 
625  def classname(self, attrs):
626  c = attrs.get((TEXTNS,'style-name'),'')
627  c = c.replace(".","_")
628  return c
629 
630 
632  def get_anchor(self, name):
633  if name not in self.anchors:
634  self.anchors[name] = "anchor%03d" % (len(self.anchors) + 1)
635  return self.anchors.get(name)
636 
637 
638 #--------------------------------------------------
639 
640  def purgedata(self):
641  self.data = []
642 
643 #-----------------------------------------------------------------------------
644 #
645 # Handle meta data
646 #
647 #-----------------------------------------------------------------------------
648 
651  def e_dc_title(self, tag, attrs):
652  self.title = ''.join(self.data)
653  #self.metatags.append('<title>%s</title>\n' % escape(self.title))
654  self.data = []
655 
656 
659  def e_dc_metatag(self, tag, attrs):
660  self.metatags.append('<meta name="%s" content=%s/>\n' % (tag[1], quoteattr(''.join(self.data))))
661  self.data = []
662 
663 
666  def e_dc_contentlanguage(self, tag, attrs):
667  self.language = ''.join(self.data)
668  self.metatags.append('<meta http-equiv="content-language" content="%s"/>\n' % escape(self.language))
669  self.data = []
670 
671 
674  def e_dc_creator(self, tag, attrs):
675  self.creator = ''.join(self.data)
676  self.metatags.append('<meta http-equiv="creator" content="%s"/>\n' % escape(self.creator))
677  self.data = []
678 
679 
682  def s_custom_shape(self, tag, attrs):
683  anchor_type = attrs.get((TEXTNS,'anchor-type'),'notfound')
684  htmltag = 'div'
685  name = "G-" + attrs.get( (DRAWNS,'style-name'), "")
686  if name == 'G-':
687  name = "PR-" + attrs.get( (PRESENTATIONNS,'style-name'), "")
688  name = name.replace(".","_")
689  if anchor_type == "paragraph":
690  style = 'position:absolute;'
691  elif anchor_type == 'char':
692  style = "position:absolute;"
693  elif anchor_type == 'as-char':
694  htmltag = 'div'
695  style = ''
696  else:
697  style = "position: absolute;"
698  if (SVGNS,"width")in attrs:
699  style = style + "width:" + attrs[(SVGNS,"width")] + ";"
700  if (SVGNS,"height") in attrs:
701  style = style + "height:" + attrs[(SVGNS,"height")] + ";"
702  if (SVGNS,"x") in attrs:
703  style = style + "left:" + attrs[(SVGNS,"x")] + ";"
704  if (SVGNS,"y") in attrs:
705  style = style + "top:" + attrs[(SVGNS,"y")] + ";"
706  if self.generate_css:
707  self.opentag(htmltag, {'class': name, 'style': style})
708  else:
709  self.opentag(htmltag)
710 
711 
714  def e_custom_shape(self, tag, attrs):
715  self.closetag('div')
716 
717 
720  def s_draw_frame(self, tag, attrs):
721  anchor_type = attrs.get((TEXTNS,'anchor-type'),'notfound')
722  htmltag = 'div'
723  name = "G-" + attrs.get( (DRAWNS,'style-name'), "")
724  if name == 'G-':
725  name = "PR-" + attrs.get( (PRESENTATIONNS,'style-name'), "")
726  name = name.replace(".","_")
727  if anchor_type == "paragraph":
728  style = 'position:relative;'
729  elif anchor_type == 'char':
730  style = "position:relative;"
731  elif anchor_type == 'as-char':
732  htmltag = 'div'
733  style = ''
734  else:
735  style = "position:absolute;"
736  if (SVGNS,"width") in attrs:
737  style = style + "width:" + attrs[(SVGNS,"width")] + ";"
738  if (SVGNS,"height") in attrs:
739  style = style + "height:" + attrs[(SVGNS,"height")] + ";"
740  if (SVGNS,"x") in attrs:
741  style = style + "left:" + attrs[(SVGNS,"x")] + ";"
742  if (SVGNS,"y") in attrs:
743  style = style + "top:" + attrs[(SVGNS,"y")] + ";"
744  if self.generate_css:
745  self.opentag(htmltag, {'class': name, 'style': style})
746  else:
747  self.opentag(htmltag)
748 
749 
752  def e_draw_frame(self, tag, attrs):
753  self.closetag('div')
754 
755  def s_draw_fill_image(self, tag, attrs):
756  name = attrs.get( (DRAWNS,'name'), "NoName")
757  imghref = attrs[(XLINKNS,"href")]
758  imghref = self.rewritelink(imghref)
759  self.cs.fillimages[name] = imghref
760 
761 
765  def rewritelink(self, imghref):
766  return imghref
767 
768 
771  def s_draw_image(self, tag, attrs):
772  parent = self.tagstack.stackparent()
773  anchor_type = parent.get((TEXTNS,'anchor-type'))
774  imghref = attrs[(XLINKNS,"href")]
775  imghref = self.rewritelink(imghref)
776  htmlattrs = {'alt':"", 'src':imghref }
777  if self.generate_css:
778  if anchor_type != "char":
779  htmlattrs['style'] = "display: block;"
780  self.emptytag('img', htmlattrs)
781 
782 
785  def s_draw_object(self, tag, attrs):
786  objhref = attrs[(XLINKNS,"href")]
787  # Remove leading "./": from "./Object 1" to "Object 1"
788  # objhref = objhref [2:]
789 
790  # Not using os.path.join since it fails to find the file on Windows.
791  # objcontentpath = '/'.join([objhref, 'content.xml'])
792  ################################
793  # fixed: self.document.childnodes ===> self.document.childobjects
794  # 2016-02-19 G.K.
795  ################################
796  for c in self.document.childobjects:
797  if c.folder == objhref:
798  self._walknode(c.topnode)
799 
800 
803  def s_draw_object_ole(self, tag, attrs):
804  class_id = attrs[(DRAWNS,"class-id")]
805  if class_id and class_id.lower() == "00020803-0000-0000-c000-000000000046": ## Microsoft Graph 97 Chart
806  tagattrs = { 'name':'object_ole_graph', 'class':'ole-graph' }
807  self.opentag('a', tagattrs)
808  self.closetag('a', tagattrs)
809 
810 
815  def s_draw_page(self, tag, attrs):
816  name = attrs.get( (DRAWNS,'name'), "NoName")
817  stylename = attrs.get( (DRAWNS,'style-name'), "")
818  stylename = stylename.replace(".","_")
819  masterpage = attrs.get( (DRAWNS,'master-page-name'),"")
820  masterpage = masterpage.replace(".","_")
821  if self.generate_css:
822  self.opentag('fieldset', {'class':"DP-%s MP-%s" % (stylename, masterpage) })
823  else:
824  self.opentag('fieldset')
825  self.opentag('legend')
826  self.writeout(escape(name))
827  self.closetag('legend')
828 
829  def e_draw_page(self, tag, attrs):
830  self.closetag('fieldset')
831 
832  def s_draw_textbox(self, tag, attrs):
833  style = ''
834  if (FONS,"min-height") in attrs:
835  style = style + "min-height:" + attrs[(FONS,"min-height")] + ";"
836  self.opentag('div')
837 # self.opentag('div', {'style': style})
838 
839 
842  def e_draw_textbox(self, tag, attrs):
843  self.closetag('div')
844 
845  def html_body(self, tag, attrs):
846  self.writedata()
847  if self.generate_css and self.use_internal_css:
848  self.opentag('style', {'type':"text/css"}, True)
849  self.writeout('/*<![CDATA[*/\n')
850  self.generate_stylesheet()
851  self.writeout('/*]]>*/\n')
852  self.closetag('style')
853  self.purgedata()
854  self.closetag('head')
855  self.opentag('body', block=True)
856 
857  default_styles = """
858 img { width: 100%; height: 100%; }
859 * { padding: 0; margin: 0; background-color:white; }
860 body { margin: 0 1em; }
861 ol, ul { padding-left: 2em; }
862 """
863 
865  for name in self.stylestack:
866  styles = self.styledict.get(name)
867  # Preload with the family's default style
868  if '__style-family'in styles and styles['__style-family'] in self.styledict:
869  familystyle = self.styledict[styles['__style-family']].copy()
870  del styles['__style-family']
871  for style, val in styles.items():
872  familystyle[style] = val
873  styles = familystyle
874  # Resolve the remaining parent styles
875  while '__parent-style-name' in styles and styles['__parent-style-name'] in self.styledict:
876  parentstyle = self.styledict[styles['__parent-style-name']].copy()
877  del styles['__parent-style-name']
878  for style, val in styles.items():
879  parentstyle[style] = val
880  styles = parentstyle
881  self.styledict[name] = styles
882  # Write the styles to HTML
883  self.writeout(self.default_styles)
884  for name in self.stylestack:
885  styles = self.styledict.get(name)
886  css2 = self.cs.convert_styles(styles)
887  self.writeout("%s {\n" % name)
888  for style, val in css2.items():
889  self.writeout("\t%s: %s;\n" % (style, val) )
890  self.writeout("}\n")
891 
893  if self.currentnote == 0:
894  return
895  if self.generate_css:
896  self.opentag('ol', {'style':'border-top: 1px solid black'}, True)
897  else:
898  self.opentag('ol')
899  for key in range(1,self.currentnote+1):
900  note = self.notedict[key]
901 # for key,note in self.notedict.items():
902  self.opentag('li', { 'id':"footnote-%d" % key })
903 # self.opentag('sup')
904 # self.writeout(escape(note['citation']))
905 # self.closetag('sup', False)
906  self.writeout(note['body'])
907  self.closetag('li')
908  self.closetag('ol')
909 
910  def s_office_automatic_styles(self, tag, attrs):
911  if self.xmlfile == 'styles.xml':
912  self.autoprefix = "A"
913  else:
914  self.autoprefix = ""
915 
916 
918  def s_office_document_content(self, tag, attrs):
919  self.writeout('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" ')
920  self.writeout('"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n')
921  self.opentag('html', {'xmlns':"http://www.w3.org/1999/xhtml"}, True)
922  self.opentag('head', block=True)
923  self.emptytag('meta', { 'http-equiv':"Content-Type", 'content':"text/html;charset=UTF-8"})
924  for metaline in self.metatags:
925  self.writeout(metaline)
926  self.writeout('<title>%s</title>\n' % escape(self.title))
927 
928 
930  def e_office_document_content(self, tag, attrs):
931  self.closetag('html')
932 
933 
935  def s_office_master_styles(self, tag, attrs):
936 
937 
942  def s_office_presentation(self, tag, attrs):
943  self.styledict['p'] = {(FONS,u'font-size'): u"24pt" }
944  self.styledict['presentation'] = {(FONS,u'font-size'): u"24pt" }
945  self.html_body(tag, attrs)
946 
947  def e_office_presentation(self, tag, attrs):
948  self.generate_footnotes()
949  self.closetag('body')
950 
951  def s_office_spreadsheet(self, tag, attrs):
952  self.html_body(tag, attrs)
953 
954  def e_office_spreadsheet(self, tag, attrs):
955  self.generate_footnotes()
956  self.closetag('body')
957 
958  def s_office_styles(self, tag, attrs):
959  self.autoprefix = ""
960 
961 
963  def s_office_text(self, tag, attrs):
964  self.styledict['frame'] = { (STYLENS,'wrap'): u'parallel'}
965  self.html_body(tag, attrs)
966 
967  def e_office_text(self, tag, attrs):
968  self.generate_footnotes()
969  self.closetag('body')
970 
971 
975  def s_style_handle_properties(self, tag, attrs):
976  for key,attr in attrs.items():
977  self.styledict[self.currentstyle][key] = attr
978 
979 
980  familymap = {'frame':'frame', 'paragraph':'p', 'presentation':'presentation',
981  'text':'span','section':'div',
982  'table':'table','table-cell':'td','table-column':'col',
983  'table-row':'tr','graphic':'graphic' }
984 
985 
988  def s_style_default_style(self, tag, attrs):
989  family = attrs[(STYLENS,'family')]
990  htmlfamily = self.familymap.get(family,'unknown')
991  self.currentstyle = htmlfamily
992 # self.stylestack.append(self.currentstyle)
993  self.styledict[self.currentstyle] = {}
994 
995  def e_style_default_style(self, tag, attrs):
996  self.currentstyle = None
997 
998 
1005  def s_style_font_face(self, tag, attrs):
1006  name = attrs[(STYLENS,"name")]
1007  family = attrs[(SVGNS,"font-family")]
1008  generic = attrs.get( (STYLENS,'font-family-generic'),"" )
1009  self.cs.save_font(name, family, generic)
1010 
1011  def s_style_footer(self, tag, attrs):
1012  self.opentag('div', { 'id':"footer" })
1013  self.purgedata()
1014 
1015  def e_style_footer(self, tag, attrs):
1016  self.writedata()
1017  self.closetag('div')
1018  self.purgedata()
1019 
1020  def s_style_footer_style(self, tag, attrs):
1021  self.currentstyle = "@print #footer"
1022  self.stylestack.append(self.currentstyle)
1023  self.styledict[self.currentstyle] = {}
1024 
1025  def s_style_header(self, tag, attrs):
1026  self.opentag('div', { 'id':"header" })
1027  self.purgedata()
1028 
1029  def e_style_header(self, tag, attrs):
1030  self.writedata()
1031  self.closetag('div')
1032  self.purgedata()
1033 
1034  def s_style_header_style(self, tag, attrs):
1035  self.currentstyle = "@print #header"
1036  self.stylestack.append(self.currentstyle)
1037  self.styledict[self.currentstyle] = {}
1038 
1039 
1042  def s_style_default_page_layout(self, tag, attrs):
1043  self.currentstyle = "@page"
1044  self.stylestack.append(self.currentstyle)
1045  self.styledict[self.currentstyle] = {}
1046 
1047 
1052  def s_style_page_layout(self, tag, attrs):
1053  name = attrs[(STYLENS,'name')]
1054  name = name.replace(".","_")
1055  self.currentstyle = ".PL-" + name
1056  self.stylestack.append(self.currentstyle)
1057  self.styledict[self.currentstyle] = {}
1058 
1059 
1062  def e_style_page_layout(self, tag, attrs):
1063  self.currentstyle = None
1064 
1065 
1068  def s_style_master_page(self, tag, attrs):
1069  name = attrs[(STYLENS,'name')]
1070  name = name.replace(".","_")
1071 
1072  self.currentstyle = ".MP-" + name
1073  self.stylestack.append(self.currentstyle)
1074  self.styledict[self.currentstyle] = {('','position'):'relative'}
1075  # Then load the pagelayout style if we find it
1076  pagelayout = attrs.get( (STYLENS,'page-layout-name'), None)
1077  if pagelayout:
1078  pagelayout = ".PL-" + pagelayout
1079  if pagelayout in self.styledict:
1080  styles = self.styledict[pagelayout]
1081  for style, val in styles.items():
1082  self.styledict[self.currentstyle][style] = val
1083  else:
1084  self.styledict[self.currentstyle]['__parent-style-name'] = pagelayout
1085  self.s_ignorexml(tag, attrs)
1086 
1087  # Short prefixes for class selectors
1088  _familyshort = {'drawing-page':'DP', 'paragraph':'P', 'presentation':'PR',
1089  'text':'S', 'section':'D',
1090  'table':'T', 'table-cell':'TD', 'table-column':'TC',
1091  'table-row':'TR', 'graphic':'G' }
1092 
1093 
1100  def s_style_style(self, tag, attrs):
1101  name = attrs[(STYLENS,'name')]
1102  name = name.replace(".","_")
1103  family = attrs[(STYLENS,'family')]
1104  htmlfamily = self.familymap.get(family,'unknown')
1105  sfamily = self._familyshort.get(family,'X')
1106  name = "%s%s-%s" % (self.autoprefix, sfamily, name)
1107  parent = attrs.get( (STYLENS,'parent-style-name') )
1108  self.currentstyle = special_styles.get(name,"."+name)
1109  self.stylestack.append(self.currentstyle)
1110  if self.currentstyle not in self.styledict:
1111  self.styledict[self.currentstyle] = {}
1112 
1113  self.styledict[self.currentstyle]['__style-family'] = htmlfamily
1114 
1115  # Then load the parent style if we find it
1116  if parent:
1117  parent = "%s-%s" % (sfamily, parent)
1118  parent = special_styles.get(parent, "."+parent)
1119  if parent in self.styledict:
1120  styles = self.styledict[parent]
1121  for style, val in styles.items():
1122  self.styledict[self.currentstyle][style] = val
1123  else:
1124  self.styledict[self.currentstyle]['__parent-style-name'] = parent
1125 
1126 
1129  def e_style_style(self, tag, attrs):
1130  self.currentstyle = None
1131 
1132 
1135  def s_table_table(self, tag, attrs):
1136  c = attrs.get( (TABLENS,'style-name'), None)
1137  if c and self.generate_css:
1138  c = c.replace(".","_")
1139  self.opentag('table',{ 'class': "T-%s" % c })
1140  else:
1141  self.opentag('table')
1142  self.purgedata()
1143 
1144 
1147  def e_table_table(self, tag, attrs):
1148  self.writedata()
1149  self.closetag('table')
1150  self.purgedata()
1151 
1152 
1154  def s_table_table_cell(self, tag, attrs):
1155  #FIXME: number-columns-repeated § 8.1.3
1156  #repeated = int(attrs.get( (TABLENS,'number-columns-repeated'), 1))
1157  htmlattrs = {}
1158  rowspan = attrs.get( (TABLENS,'number-rows-spanned') )
1159  if rowspan:
1160  htmlattrs['rowspan'] = rowspan
1161  colspan = attrs.get( (TABLENS,'number-columns-spanned') )
1162  if colspan:
1163  htmlattrs['colspan'] = colspan
1164 
1165  c = attrs.get( (TABLENS,'style-name') )
1166  if c:
1167  htmlattrs['class'] = 'TD-%s' % c.replace(".","_")
1168  self.opentag('td', htmlattrs)
1169  self.purgedata()
1170 
1171 
1173  def e_table_table_cell(self, tag, attrs):
1174  self.writedata()
1175  self.closetag('td')
1176  self.purgedata()
1177 
1178 
1180  def s_table_table_column(self, tag, attrs):
1181  c = attrs.get( (TABLENS,'style-name'), None)
1182  repeated = int(attrs.get( (TABLENS,'number-columns-repeated'), 1))
1183  htmlattrs = {}
1184  if c:
1185  htmlattrs['class'] = "TC-%s" % c.replace(".","_")
1186  for x in range(repeated):
1187  self.emptytag('col', htmlattrs)
1188  self.purgedata()
1189 
1190 
1192  def s_table_table_row(self, tag, attrs):
1193  #FIXME: table:number-rows-repeated
1194  c = attrs.get( (TABLENS,'style-name'), None)
1195  htmlattrs = {}
1196  if c:
1197  htmlattrs['class'] = "TR-%s" % c.replace(".","_")
1198  self.opentag('tr', htmlattrs)
1199  self.purgedata()
1200 
1201 
1203  def e_table_table_row(self, tag, attrs):
1204  self.writedata()
1205  self.closetag('tr')
1206  self.purgedata()
1207 
1208 
1210  def s_text_a(self, tag, attrs):
1211  self.writedata()
1212  href = attrs[(XLINKNS,"href")].split("|")[0]
1213  if href[0] == "#":
1214  href = "#" + self.get_anchor(href[1:])
1215  self.opentag('a', {'href':href})
1216  self.purgedata()
1217 
1218 
1220  def e_text_a(self, tag, attrs):
1221  self.writedata()
1222  self.closetag('a', False)
1223  self.purgedata()
1224 
1225 
1227  def s_text_bookmark(self, tag, attrs):
1228  name = attrs[(TEXTNS,'name')]
1229  html_id = self.get_anchor(name)
1230  self.writedata()
1231  self.opentag('span', {'id':html_id})
1232  self.closetag('span', False)
1233  self.purgedata()
1234 
1235 
1237  def s_text_bookmark_ref(self, tag, attrs):
1238  name = attrs[(TEXTNS,'ref-name')]
1239  html_id = "#" + self.get_anchor(name)
1240  self.writedata()
1241  self.opentag('a', {'href':html_id})
1242  self.purgedata()
1243 
1244 
1246  def s_text_h(self, tag, attrs):
1247  level = int(attrs[(TEXTNS,'outline-level')])
1248  if level > 6: level = 6 # Heading levels go only to 6 in XHTML
1249  if level < 1: level = 1
1250  self.headinglevels[level] = self.headinglevels[level] + 1
1251  name = self.classname(attrs)
1252  for x in range(level + 1,10):
1253  self.headinglevels[x] = 0
1254  special = special_styles.get("P-"+name)
1255  if special or not self.generate_css:
1256  self.opentag('h%s' % level)
1257  else:
1258  self.opentag('h%s' % level, {'class':"P-%s" % name })
1259  self.purgedata()
1260 
1261 
1266  def e_text_h(self, tag, attrs):
1267  self.writedata()
1268  level = int(attrs[(TEXTNS,'outline-level')])
1269  if level > 6: level = 6 # Heading levels go only to 6 in XHTML
1270  if level < 1: level = 1
1271  lev = self.headinglevels[1:level+1]
1272  outline = '.'.join(map(str,lev) )
1273  heading = ''.join(self.data)
1274  if self.title == '': self.title = heading
1275  anchor = self.get_anchor("%s.%s" % ( outline, heading))
1276  self.opentag('a', {'id': anchor} )
1277  self.closetag('a', False)
1278  self.closetag('h%s' % level)
1279  self.purgedata()
1280 
1281 
1283  def s_text_line_break(self, tag, attrs):
1284  self.writedata()
1285  self.emptytag('br')
1286  self.purgedata()
1287 
1288 
1293  def s_text_list(self, tag, attrs):
1294  name = attrs.get( (TEXTNS,'style-name') )
1295  level = self.tagstack.count_tags(tag) + 1
1296  if name:
1297  name = name.replace(".","_")
1298  else:
1299  # FIXME: If a list is contained in a table cell or text box,
1300  # the list level must return to 1, even though the table or
1301  # textbox itself may be nested within another list.
1302  name = self.tagstack.rfindattr( (TEXTNS,'style-name') )
1303  list_class = "%s_%d" % (name, level)
1304  if self.generate_css:
1305  self.opentag('%s' % self.listtypes.get(list_class,'ul'), {'class': list_class })
1306  else:
1307  self.opentag('%s' % self.listtypes.get(list_class,'ul'))
1308  self.purgedata()
1309 
1310 
1312  def e_text_list(self, tag, attrs):
1313  self.writedata()
1314  name = attrs.get( (TEXTNS,'style-name') )
1315  level = self.tagstack.count_tags(tag) + 1
1316  if name:
1317  name = name.replace(".","_")
1318  else:
1319  # FIXME: If a list is contained in a table cell or text box,
1320  # the list level must return to 1, even though the table or
1321  # textbox itself may be nested within another list.
1322  name = self.tagstack.rfindattr( (TEXTNS,'style-name') )
1323  list_class = "%s_%d" % (name, level)
1324  self.closetag(self.listtypes.get(list_class,'ul'))
1325  self.purgedata()
1326 
1327 
1329  def s_text_list_item(self, tag, attrs):
1330  self.opentag('li')
1331  self.purgedata()
1332 
1333 
1335  def e_text_list_item(self, tag, attrs):
1336  self.writedata()
1337  self.closetag('li')
1338  self.purgedata()
1339 
1340 
1345  def s_text_list_level_style_bullet(self, tag, attrs):
1346  name = self.tagstack.rfindattr( (STYLENS,'name') )
1347  level = attrs[(TEXTNS,'level')]
1349  list_class = "%s_%s" % (name, level)
1350  self.listtypes[list_class] = 'ul'
1351  self.currentstyle = ".%s_%s" % ( name.replace(".","_"), level)
1352  self.stylestack.append(self.currentstyle)
1353  self.styledict[self.currentstyle] = {}
1354 
1355  level = int(level)
1356  listtype = ("square", "disc", "circle")[level % 3]
1357  self.styledict[self.currentstyle][('','list-style-type')] = listtype
1358 
1359  def e_text_list_level_style_bullet(self, tag, attrs):
1360  self.currentstyle = self.prevstyle
1361  del self.prevstyle
1362 
1363  def s_text_list_level_style_number(self, tag, attrs):
1364  name = self.tagstack.stackparent()[(STYLENS,'name')]
1365  level = attrs[(TEXTNS,'level')]
1366  num_format = attrs.get( (STYLENS,'name'),"1")
1367  list_class = "%s_%s" % (name, level)
1368  self.prevstyle = self.currentstyle
1369  self.currentstyle = ".%s_%s" % ( name.replace(".","_"), level)
1370  self.listtypes[list_class] = 'ol'
1371  self.stylestack.append(self.currentstyle)
1372  self.styledict[self.currentstyle] = {}
1373  if num_format == "1": listtype = "decimal"
1374  elif num_format == "I": listtype = "upper-roman"
1375  elif num_format == "i": listtype = "lower-roman"
1376  elif num_format == "A": listtype = "upper-alpha"
1377  elif num_format == "a": listtype = "lower-alpha"
1378  else: listtype = "decimal"
1379  self.styledict[self.currentstyle][('','list-style-type')] = listtype
1380 
1381  def e_text_list_level_style_number(self, tag, attrs):
1382  self.currentstyle = self.prevstyle
1383  del self.prevstyle
1384 
1385  def s_text_note(self, tag, attrs):
1386  self.writedata()
1387  self.purgedata()
1388  self.currentnote = self.currentnote + 1
1389  self.notedict[self.currentnote] = {}
1390  self.notebody = []
1391 
1392  def e_text_note(self, tag, attrs):
1393  pass
1394 
1395  def collectnote(self,s):
1396  if s != '':
1397  self.notebody.append(s)
1398 
1399  def s_text_note_body(self, tag, attrs):
1400  self._orgwfunc = self._wfunc
1401  self._wfunc = self.collectnote
1402 
1403  def e_text_note_body(self, tag, attrs):
1404  self._wfunc = self._orgwfunc
1405  self.notedict[self.currentnote]['body'] = ''.join(self.notebody)
1406  self.notebody = ''
1407  del self._orgwfunc
1408 
1409  def e_text_note_citation(self, tag, attrs):
1410  mark = ''.join(self.data)
1411  self.notedict[self.currentnote]['citation'] = mark
1412  self.opentag('a',{ 'href': "#footnote-%s" % self.currentnote })
1413  self.opentag('sup')
1414 # self.writeout( escape(mark) )
1415  # Since HTML only knows about endnotes, there is too much risk that the
1416  # marker is reused in the source. Therefore we force numeric markers
1417  if sys.version_info[0]==3:
1418  self.writeout(self.currentnote)
1419  else:
1420  self.writeout(unicode(self.currentnote))
1421  self.closetag('sup')
1422  self.closetag('a')
1423 
1424 
1427  def s_text_p(self, tag, attrs):
1428  htmlattrs = {}
1429  specialtag = "p"
1430  c = attrs.get( (TEXTNS,'style-name'), None)
1431  if c:
1432  c = c.replace(".","_")
1433  specialtag = special_styles.get("P-"+c)
1434  if specialtag is None:
1435  specialtag = 'p'
1436  if self.generate_css:
1437  htmlattrs['class'] = "P-%s" % c
1438  self.opentag(specialtag, htmlattrs)
1439  self.purgedata()
1440 
1441 
1444  def e_text_p(self, tag, attrs):
1445  specialtag = "p"
1446  c = attrs.get( (TEXTNS,'style-name'), None)
1447  if c:
1448  c = c.replace(".","_")
1449  specialtag = special_styles.get("P-"+c)
1450  if specialtag is None:
1451  specialtag = 'p'
1452  self.writedata()
1453  self.closetag(specialtag)
1454  self.purgedata()
1455 
1456 
1460  def s_text_s(self, tag, attrs):
1461  c = attrs.get( (TEXTNS,'c'),"1")
1462  for x in range(int(c)):
1463  self.writeout('&#160;')
1464 
1465 
1469  def s_text_span(self, tag, attrs):
1470  self.writedata()
1471  c = attrs.get( (TEXTNS,'style-name'), None)
1472  htmlattrs = {}
1473  if c:
1474  c = c.replace(".","_")
1475  special = special_styles.get("S-"+c)
1476  if special is None and self.generate_css:
1477  htmlattrs['class'] = "S-%s" % c
1478  self.opentag('span', htmlattrs)
1479  self.purgedata()
1480 
1481 
1483  def e_text_span(self, tag, attrs):
1484  self.writedata()
1485  self.closetag('span', False)
1486  self.purgedata()
1487 
1488 
1491  def s_text_tab(self, tag, attrs):
1492  self.writedata()
1493  self.writeout(' ')
1494  self.purgedata()
1495 
1496 
1499  def s_text_x_source(self, tag, attrs):
1500  self.writedata()
1501  self.purgedata()
1502  self.s_ignorexml(tag, attrs)
1503 
1504 
1507  def e_text_x_source(self, tag, attrs):
1508  self.writedata()
1509  self.purgedata()
1510 
1511 
1512 #-----------------------------------------------------------------------------
1513 #
1514 # Reading the file
1515 #
1516 #-----------------------------------------------------------------------------
1517 
1518 
1525  def load(self, odffile):
1526  assert(type(odffile)==type(u"") or 'rb' in repr(odffile) or 'BufferedReader' in repr(odffile) or 'BytesIO' in repr(odffile))
1527 
1528  self.lines = []
1529  self._wfunc = self._wlines
1530  if type(odffile)==type(u""):
1531  self.document = load(odffile)
1532  else:
1533  self.document = odffile
1534  self._walknode(self.document.topnode)
1535 
1536  def _walknode(self, node):
1537  if node.nodeType == Node.ELEMENT_NODE:
1538  self.startElementNS(node.qname, node.tagName, node.attributes)
1539  for c in node.childNodes:
1540  self._walknode(c)
1541  self.endElementNS(node.qname, node.tagName)
1542  if node.nodeType == Node.TEXT_NODE or node.nodeType == Node.CDATA_SECTION_NODE:
1543  if sys.version_info[0]==3:
1544  self.characters(str(node))
1545  else:
1546  self.characters(unicode(node))
1547 
1548 
1549 
1556  def odf2xhtml(self, odffile):
1557  assert(type(odffile)==type(u"") or 'rb' in repr(odffile) or 'BufferedReader' in repr(odffile) or 'BytesIO' in repr(odffile))
1558 
1559 
1560  self.load(odffile)
1561 
1562  result=self.xhtml()
1563  assert(type(result)==type(u""))
1564  return result
1565 
1566  def _wlines(self,s):
1567  if s != '': self.lines.append(s)
1568 
1569 
1572  def xhtml(self):
1573  return ''.join(self.lines)
1574 
1575  def _writecss(self, s):
1576  if s != '': self._csslines.append(s)
1577 
1578  def _writenothing(self, s):
1579  pass
1580 
1581 
1583  def css(self):
1584  self._csslines = []
1585  self._wfunc = self._writecss
1586  self.generate_stylesheet()
1587  res = ''.join(self._csslines)
1588  self._wfunc = self._wlines
1589  del self._csslines
1590  return res
1591 
1592 
1597  def save(self, outputfile, addsuffix=False):
1598  if outputfile == '-':
1599  outputfp = sys.stdout
1600  else:
1601  if addsuffix:
1602  outputfile = outputfile + ".html"
1603  outputfp = file(outputfile, "w")
1604  outputfp.write(self.xhtml().encode('us-ascii','xmlcharrefreplace'))
1605  outputfp.close()
1606 
1607 
1608 
1611 
1612  def __init__(self, lines, generate_css=True, embedable=False):
1613  self._resetobject()
1614  self.lines = lines
1615 
1616  # Tags
1617  self.generate_css = generate_css
1618  self.elements = {
1619 # (DCNS, 'title'): (self.s_processcont, self.e_dc_title),
1620 # (DCNS, 'language'): (self.s_processcont, self.e_dc_contentlanguage),
1621 # (DCNS, 'creator'): (self.s_processcont, self.e_dc_metatag),
1622 # (DCNS, 'description'): (self.s_processcont, self.e_dc_metatag),
1623 # (DCNS, 'date'): (self.s_processcont, self.e_dc_metatag),
1624  (DRAWNS, 'frame'): (self.s_draw_frame, self.e_draw_frame),
1625  (DRAWNS, 'image'): (self.s_draw_image, None),
1626  (DRAWNS, 'fill-image'): (self.s_draw_fill_image, None),
1627  (DRAWNS, "layer-set"):(self.s_ignorexml, None),
1628  (DRAWNS, 'page'): (self.s_draw_page, self.e_draw_page),
1629  (DRAWNS, 'object'): (self.s_draw_object, None),
1630  (DRAWNS, 'object-ole'): (self.s_draw_object_ole, None),
1631  (DRAWNS, 'text-box'): (self.s_draw_textbox, self.e_draw_textbox),
1632 # (METANS, 'creation-date'):(self.s_processcont, self.e_dc_metatag),
1633 # (METANS, 'generator'):(self.s_processcont, self.e_dc_metatag),
1634 # (METANS, 'initial-creator'): (self.s_processcont, self.e_dc_metatag),
1635 # (METANS, 'keyword'): (self.s_processcont, self.e_dc_metatag),
1636  (NUMBERNS, "boolean-style"):(self.s_ignorexml, None),
1637  (NUMBERNS, "currency-style"):(self.s_ignorexml, None),
1638  (NUMBERNS, "date-style"):(self.s_ignorexml, None),
1639  (NUMBERNS, "number-style"):(self.s_ignorexml, None),
1640  (NUMBERNS, "text-style"):(self.s_ignorexml, None),
1641 # (OFFICENS, "automatic-styles"):(self.s_office_automatic_styles, None),
1642 # (OFFICENS, "document-content"):(self.s_office_document_content, self.e_office_document_content),
1643  (OFFICENS, "forms"):(self.s_ignorexml, None),
1644 # (OFFICENS, "master-styles"):(self.s_office_master_styles, None),
1645  (OFFICENS, "meta"):(self.s_ignorecont, None),
1646 # (OFFICENS, "presentation"):(self.s_office_presentation, self.e_office_presentation),
1647 # (OFFICENS, "spreadsheet"):(self.s_office_spreadsheet, self.e_office_spreadsheet),
1648 # (OFFICENS, "styles"):(self.s_office_styles, None),
1649 # (OFFICENS, "text"):(self.s_office_text, self.e_office_text),
1650  (OFFICENS, "scripts"):(self.s_ignorexml, None),
1651  (PRESENTATIONNS, "notes"):(self.s_ignorexml, None),
1652 ## (STYLENS, "default-page-layout"):(self.s_style_default_page_layout, self.e_style_page_layout),
1653 # (STYLENS, "default-page-layout"):(self.s_ignorexml, None),
1654 # (STYLENS, "default-style"):(self.s_style_default_style, self.e_style_default_style),
1655 # (STYLENS, "drawing-page-properties"):(self.s_style_handle_properties, None),
1656 # (STYLENS, "font-face"):(self.s_style_font_face, None),
1657 ## (STYLENS, "footer"):(self.s_style_footer, self.e_style_footer),
1658 ## (STYLENS, "footer-style"):(self.s_style_footer_style, None),
1659 # (STYLENS, "graphic-properties"):(self.s_style_handle_properties, None),
1660 # (STYLENS, "handout-master"):(self.s_ignorexml, None),
1661 ## (STYLENS, "header"):(self.s_style_header, self.e_style_header),
1662 ## (STYLENS, "header-footer-properties"):(self.s_style_handle_properties, None),
1663 ## (STYLENS, "header-style"):(self.s_style_header_style, None),
1664 # (STYLENS, "master-page"):(self.s_style_master_page, None),
1665 # (STYLENS, "page-layout-properties"):(self.s_style_handle_properties, None),
1666 ## (STYLENS, "page-layout"):(self.s_style_page_layout, self.e_style_page_layout),
1667 # (STYLENS, "page-layout"):(self.s_ignorexml, None),
1668 # (STYLENS, "paragraph-properties"):(self.s_style_handle_properties, None),
1669 # (STYLENS, "style"):(self.s_style_style, self.e_style_style),
1670 # (STYLENS, "table-cell-properties"):(self.s_style_handle_properties, None),
1671 # (STYLENS, "table-column-properties"):(self.s_style_handle_properties, None),
1672 # (STYLENS, "table-properties"):(self.s_style_handle_properties, None),
1673 # (STYLENS, "text-properties"):(self.s_style_handle_properties, None),
1674  (SVGNS, 'desc'): (self.s_ignorexml, None),
1675  (TABLENS, 'covered-table-cell'): (self.s_ignorexml, None),
1676  (TABLENS, 'table-cell'): (self.s_table_table_cell, self.e_table_table_cell),
1677  (TABLENS, 'table-column'): (self.s_table_table_column, None),
1678  (TABLENS, 'table-row'): (self.s_table_table_row, self.e_table_table_row),
1679  (TABLENS, 'table'): (self.s_table_table, self.e_table_table),
1680  (TEXTNS, 'a'): (self.s_text_a, self.e_text_a),
1681  (TEXTNS, "alphabetical-index-source"):(self.s_text_x_source, self.e_text_x_source),
1682  (TEXTNS, "bibliography-configuration"):(self.s_ignorexml, None),
1683  (TEXTNS, "bibliography-source"):(self.s_text_x_source, self.e_text_x_source),
1684  (TEXTNS, 'h'): (self.s_text_h, self.e_text_h),
1685  (TEXTNS, "illustration-index-source"):(self.s_text_x_source, self.e_text_x_source),
1686  (TEXTNS, 'line-break'):(self.s_text_line_break, None),
1687  (TEXTNS, "linenumbering-configuration"):(self.s_ignorexml, None),
1688  (TEXTNS, "list"):(self.s_text_list, self.e_text_list),
1689  (TEXTNS, "list-item"):(self.s_text_list_item, self.e_text_list_item),
1690  (TEXTNS, "list-level-style-bullet"):(self.s_text_list_level_style_bullet, self.e_text_list_level_style_bullet),
1691  (TEXTNS, "list-level-style-number"):(self.s_text_list_level_style_number, self.e_text_list_level_style_number),
1692  (TEXTNS, "list-style"):(None, None),
1693  (TEXTNS, "note"):(self.s_text_note, None),
1694  (TEXTNS, "note-body"):(self.s_text_note_body, self.e_text_note_body),
1695  (TEXTNS, "note-citation"):(None, self.e_text_note_citation),
1696  (TEXTNS, "notes-configuration"):(self.s_ignorexml, None),
1697  (TEXTNS, "object-index-source"):(self.s_text_x_source, self.e_text_x_source),
1698  (TEXTNS, 'p'): (self.s_text_p, self.e_text_p),
1699  (TEXTNS, 's'): (self.s_text_s, None),
1700  (TEXTNS, 'span'): (self.s_text_span, self.e_text_span),
1701  (TEXTNS, 'tab'): (self.s_text_tab, None),
1702  (TEXTNS, "table-index-source"):(self.s_text_x_source, self.e_text_x_source),
1703  (TEXTNS, "table-of-content-source"):(self.s_text_x_source, self.e_text_x_source),
1704  (TEXTNS, "user-index-source"):(self.s_text_x_source, self.e_text_x_source),
1705  (TEXTNS, "page-number"):(None, None),
1706  }
1707 
def generate_stylesheet(self)
Definition: odf2xhtml.py:864
def rfindattr(self, attr)
Find a tag with the given attribute.
Definition: odf2xhtml.py:321
def s_style_default_page_layout(self, tag, attrs)
Collect the formatting for the default page layout style.
Definition: odf2xhtml.py:1042
def opentag(self, tag, attrs={}, block=False)
Create an open HTML tag.
Definition: odf2xhtml.py:540
def e_text_h(self, tag, attrs)
Headings end Side-effect: If there is no title in the metadata, then it is taken from the first headi...
Definition: odf2xhtml.py:1266
def s_draw_page(self, tag, attrs)
A <draw:page> is a slide in a presentation.
Definition: odf2xhtml.py:815
def e_dc_contentlanguage(self, tag, attrs)
Set the content language.
Definition: odf2xhtml.py:666
def e_dc_metatag(self, tag, attrs)
Any other meta data is added as a <meta> element.
Definition: odf2xhtml.py:659
def c_hp(self, ruleset, sdict, rule, hpos)
Definition: odf2xhtml.py:207
def unknown_endtag(self, tag, attrs)
Definition: odf2xhtml.py:603
def s_draw_image(self, tag, attrs)
A <draw:image> becomes an element.
Definition: odf2xhtml.py:771
def emptytag(self, tag, attrs={})
Definition: odf2xhtml.py:560
def s_style_header(self, tag, attrs)
Definition: odf2xhtml.py:1025
def html_body(self, tag, attrs)
Definition: odf2xhtml.py:845
def closetag(self, tag, block=True)
Close an open HTML tag.
Definition: odf2xhtml.py:554
def e_custom_shape(self, tag, attrs)
End the <draw:frame>
Definition: odf2xhtml.py:714
def classname(self, attrs)
Generate a class name from a style name.
Definition: odf2xhtml.py:625
def _walknode(self, node)
Definition: odf2xhtml.py:1536
def e_style_style(self, tag, attrs)
End this style.
Definition: odf2xhtml.py:1129
def s_style_handle_properties(self, tag, attrs)
Copy all attributes to a struct.
Definition: odf2xhtml.py:975
def s_table_table_cell(self, tag, attrs)
Start a table cell.
Definition: odf2xhtml.py:1154
def _wlines(self, s)
Definition: odf2xhtml.py:1566
def e_text_note(self, tag, attrs)
Definition: odf2xhtml.py:1392
def e_draw_page(self, tag, attrs)
Definition: odf2xhtml.py:829
def e_text_note_body(self, tag, attrs)
Definition: odf2xhtml.py:1403
def unknown_starttag(self, tag, attrs)
Definition: odf2xhtml.py:600
def e_text_list_item(self, tag, attrs)
End list item.
Definition: odf2xhtml.py:1335
def s_style_master_page(self, tag, attrs)
Collect the formatting for the page layout style.
Definition: odf2xhtml.py:1068
def __init__(self, lines, generate_css=True, embedable=False)
Definition: odf2xhtml.py:1612
def e_office_spreadsheet(self, tag, attrs)
Definition: odf2xhtml.py:954
def collectnote(self, s)
Definition: odf2xhtml.py:1395
def s_style_page_layout(self, tag, attrs)
Collect the formatting for the page layout style.
Definition: odf2xhtml.py:1052
def set_embedable(self)
Tells the converter to only output the parts inside the <body>
Definition: odf2xhtml.py:474
def s_draw_object_ole(self, tag, attrs)
A <draw:object-ole> is embedded OLE object in the document (e.g.
Definition: odf2xhtml.py:803
def push(self, tag, attrs)
Definition: odf2xhtml.py:308
def s_office_spreadsheet(self, tag, attrs)
Definition: odf2xhtml.py:951
def s_office_automatic_styles(self, tag, attrs)
Definition: odf2xhtml.py:910
def s_style_header_style(self, tag, attrs)
Definition: odf2xhtml.py:1034
def e_draw_frame(self, tag, attrs)
End the <draw:frame>
Definition: odf2xhtml.py:752
def s_draw_fill_image(self, tag, attrs)
Definition: odf2xhtml.py:755
def s_ignorexml(self, tag, attrs)
Ignore this xml element and all children of it It will automatically stop ignoring.
Definition: odf2xhtml.py:610
def s_ignorecont(self, tag, attrs)
Stop processing the text nodes.
Definition: odf2xhtml.py:615
def s_draw_object(self, tag, attrs)
A <draw:object> is embedded object in the document (e.g.
Definition: odf2xhtml.py:785
def e_text_list(self, tag, attrs)
End a list.
Definition: odf2xhtml.py:1312
def s_office_text(self, tag, attrs)
OpenDocument text.
Definition: odf2xhtml.py:963
def handle_endtag(self, tag, attrs, method)
Definition: odf2xhtml.py:597
def e_style_default_style(self, tag, attrs)
Definition: odf2xhtml.py:995
def s_processcont(self, tag, attrs)
Start processing the text nodes.
Definition: odf2xhtml.py:620
def s_office_master_styles(self, tag, attrs)
Definition: odf2xhtml.py:935
def e_text_p(self, tag, attrs)
End Paragraph.
Definition: odf2xhtml.py:1444
def s_text_span(self, tag, attrs)
The <text:span> element matches the element in HTML.
Definition: odf2xhtml.py:1469
def e_table_table_cell(self, tag, attrs)
End a table cell.
Definition: odf2xhtml.py:1173
def startElementNS(self, tag, qname, attrs)
Definition: odf2xhtml.py:573
def s_text_list_level_style_number(self, tag, attrs)
Definition: odf2xhtml.py:1363
def e_text_span(self, tag, attrs)
End the <text:span>
Definition: odf2xhtml.py:1483
def characters(self, data)
Definition: odf2xhtml.py:569
def s_draw_textbox(self, tag, attrs)
Definition: odf2xhtml.py:832
def s_text_s(self, tag, attrs)
Generate a number of spaces.
Definition: odf2xhtml.py:1460
def s_style_footer(self, tag, attrs)
Definition: odf2xhtml.py:1011
def e_text_x_source(self, tag, attrs)
Various indexes and tables of contents.
Definition: odf2xhtml.py:1507
def c_text_align(self, ruleset, sdict, rule, align)
Text align.
Definition: odf2xhtml.py:159
def s_office_styles(self, tag, attrs)
Definition: odf2xhtml.py:958
def e_style_page_layout(self, tag, attrs)
End this style.
Definition: odf2xhtml.py:1062
def e_draw_textbox(self, tag, attrs)
End the <draw:text-box>
Definition: odf2xhtml.py:842
def s_text_p(self, tag, attrs)
Paragraph.
Definition: odf2xhtml.py:1427
def get_anchor(self, name)
Create a unique anchor id for a href name.
Definition: odf2xhtml.py:632
def s_text_h(self, tag, attrs)
Headings start.
Definition: odf2xhtml.py:1246
def s_text_list_level_style_bullet(self, tag, attrs)
CSS doesn&#39;t have the ability to set the glyph to a particular character, so we just go through the av...
Definition: odf2xhtml.py:1345
def s_text_bookmark(self, tag, attrs)
Bookmark definition.
Definition: odf2xhtml.py:1227
def save_font(self, name, family, generic)
It is possible that the HTML browser doesn&#39;t know how to show a particular font.
Definition: odf2xhtml.py:120
def s_table_table_column(self, tag, attrs)
Start a table column.
Definition: odf2xhtml.py:1180
def c_text_underline_style(self, ruleset, sdict, rule, val)
Set underline decoration HTML doesn&#39;t really have a page-width.
Definition: odf2xhtml.py:260
def s_text_x_source(self, tag, attrs)
Various indexes and tables of contents.
Definition: odf2xhtml.py:1499
def s_text_bookmark_ref(self, tag, attrs)
Bookmark reference.
Definition: odf2xhtml.py:1237
def s_style_style(self, tag, attrs)
Collect the formatting for the style.
Definition: odf2xhtml.py:1100
def _resetfootnotes(self)
Definition: odf2xhtml.py:493
def odf2xhtml(self, odffile)
Load a file and return the XHTML.
Definition: odf2xhtml.py:1556
def c_fn(self, ruleset, sdict, rule, fontstyle)
Generate the CSS font family A generic font can be found in two ways.
Definition: odf2xhtml.py:169
def s_text_tab(self, tag, attrs)
Move to the next tabstop.
Definition: odf2xhtml.py:1491
def s_text_line_break(self, tag, attrs)
Force a line break ( )
Definition: odf2xhtml.py:1283
def s_table_table_row(self, tag, attrs)
Start a table row.
Definition: odf2xhtml.py:1192
def c_border_model(self, ruleset, sdict, rule, val)
Convert to CSS2 border model.
Definition: odf2xhtml.py:146
def s_style_default_style(self, tag, attrs)
A default style is like a style on an HTML tag.
Definition: odf2xhtml.py:988
def set_plain(self)
Tell the parser to not generate CSS.
Definition: odf2xhtml.py:469
def e_text_note_citation(self, tag, attrs)
Definition: odf2xhtml.py:1409
def s_table_table(self, tag, attrs)
Start a table.
Definition: odf2xhtml.py:1135
def css(self)
Returns the CSS content.
Definition: odf2xhtml.py:1583
def rewritelink(self, imghref)
Intended to be overloaded if you don&#39;t store your pictures in a Pictures subfolder.
Definition: odf2xhtml.py:765
def e_text_list_level_style_bullet(self, tag, attrs)
Definition: odf2xhtml.py:1359
def c_width(self, ruleset, sdict, rule, val)
Set width of box.
Definition: odf2xhtml.py:154
def e_office_text(self, tag, attrs)
Definition: odf2xhtml.py:967
def handle_starttag(self, tag, method, attrs)
Definition: odf2xhtml.py:594
def __init__(self, generate_css=True, embedable=False)
Definition: odf2xhtml.py:364
def e_text_list_level_style_number(self, tag, attrs)
Definition: odf2xhtml.py:1381
def s_text_list_item(self, tag, attrs)
Start list item.
Definition: odf2xhtml.py:1329
def s_office_presentation(self, tag, attrs)
For some odd reason, OpenOffice Impress doesn&#39;t define a default-style for the &#39;paragraph&#39;.
Definition: odf2xhtml.py:942
The ODF2XHTML parses an ODF file and produces XHTML.
Definition: odf2xhtml.py:362
def e_dc_title(self, tag, attrs)
Get the title from the meta data and create a HTML <title>
Definition: odf2xhtml.py:651
def s_text_note(self, tag, attrs)
Definition: odf2xhtml.py:1385
def e_office_document_content(self, tag, attrs)
Last tag.
Definition: odf2xhtml.py:930
def e_text_a(self, tag, attrs)
End an anchor or bookmark reference.
Definition: odf2xhtml.py:1220
def load(self, odffile)
Loads a document into the parser and parses it.
Definition: odf2xhtml.py:1525
def c_fo(self, ruleset, sdict, rule, val)
XSL formatting attributes.
Definition: odf2xhtml.py:140
def save(self, outputfile, addsuffix=False)
Save the HTML under the filename.
Definition: odf2xhtml.py:1597
def endElementNS(self, tag, qname)
Definition: odf2xhtml.py:583
The ODF2XHTML parses an ODF file and produces XHTML.
Definition: odf2xhtml.py:1610
def s_custom_shape(self, tag, attrs)
A <draw:custom-shape> is made into a in HTML which is then styled.
Definition: odf2xhtml.py:682
def xhtml(self)
Returns the xhtml.
Definition: odf2xhtml.py:1572
def _writecss(self, s)
Definition: odf2xhtml.py:1575
def s_text_list(self, tag, attrs)
Start a list (.
Definition: odf2xhtml.py:1293
def s_text_note_body(self, tag, attrs)
Definition: odf2xhtml.py:1399
The purpose of the StyleToCSS class is to contain the rules to convert ODF styles to CSS2...
Definition: odf2xhtml.py:62
def convert_styles(self, ruleset)
Rule is a tuple of (namespace, name).
Definition: odf2xhtml.py:281
def generate_footnotes(self)
Definition: odf2xhtml.py:892
def add_style_file(self, stylefilename, media=None)
Add a link to an external style file.
Definition: odf2xhtml.py:485
def c_drawfillimage(self, ruleset, sdict, rule, val)
Fill a figure with an image.
Definition: odf2xhtml.py:135
def s_text_a(self, tag, attrs)
Anchors start.
Definition: odf2xhtml.py:1210
def e_office_presentation(self, tag, attrs)
Definition: odf2xhtml.py:947
def writeout(self, s)
Definition: odf2xhtml.py:529
def e_style_footer(self, tag, attrs)
Definition: odf2xhtml.py:1015
def e_dc_creator(self, tag, attrs)
Set the content creator.
Definition: odf2xhtml.py:674
def s_style_font_face(self, tag, attrs)
It is possible that the HTML browser doesn&#39;t know how to show a particular font.
Definition: odf2xhtml.py:1005
def e_table_table_row(self, tag, attrs)
End a table row.
Definition: odf2xhtml.py:1203
def e_table_table(self, tag, attrs)
End a table.
Definition: odf2xhtml.py:1147
def count_tags(self, tag)
Definition: odf2xhtml.py:326
def c_text_line_through_style(self, ruleset, sdict, rule, val)
Set underline decoration HTML doesn&#39;t really have a page-width.
Definition: odf2xhtml.py:268
def s_style_footer_style(self, tag, attrs)
Definition: odf2xhtml.py:1020
def c_page_width(self, ruleset, sdict, rule, val)
Set width of box HTML doesn&#39;t really have a page-width.
Definition: odf2xhtml.py:253
def c_page_height(self, ruleset, sdict, rule, val)
Set height of box.
Definition: odf2xhtml.py:274
def s_draw_frame(self, tag, attrs)
A <draw:frame> is made into a in HTML which is then styled.
Definition: odf2xhtml.py:720
def s_office_document_content(self, tag, attrs)
First tag in the content.xml file.
Definition: odf2xhtml.py:918
def c_text_position(self, ruleset, sdict, rule, tp)
Text position.
Definition: odf2xhtml.py:195
def e_style_header(self, tag, attrs)
Definition: odf2xhtml.py:1029