X-Git-Url: https://git.mdrn.pl/librarian.git/blobdiff_plain/6d65ed2b0c5f9f6df14de211ea2bf1de0a5dac70..3a70fb37a8784ea703eb23d8b19b90bfd00f13bc:/librarian/html.py diff --git a/librarian/html.py b/librarian/html.py index 4e9abd0..39e5a01 100644 --- a/librarian/html.py +++ b/librarian/html.py @@ -5,17 +5,16 @@ # import os import cStringIO -import re import copy from lxml import etree -from librarian.parser import WLDocument -from librarian import XHTMLNS, ParseError +from librarian import XHTMLNS, ParseError, OutputFile from librarian import functions from lxml.etree import XMLSyntaxError, XSLTApplyError functions.reg_substitute_entities() +functions.reg_person_name() STYLESHEETS = { 'legacy': 'xslt/book2html.xslt', @@ -29,9 +28,8 @@ def get_stylesheet(name): def html_has_content(text): return etree.ETXPath('//p|//{%(ns)s}p|//h1|//{%(ns)s}h1' % {'ns': str(XHTMLNS)})(text) -def transform(input, output_filename=None, is_file=True, \ - parse_dublincore=True, stylesheet='legacy', options={}, flags=None): - """Transforms file input_filename in XML to output_filename in XHTML. +def transform(wldoc, stylesheet='legacy', options=None, flags=None): + """Transforms the WL document to XHTML. If output_filename is None, returns an XML, otherwise returns True if file has been written,False if it hasn't. @@ -42,12 +40,9 @@ def transform(input, output_filename=None, is_file=True, \ style_filename = get_stylesheet(stylesheet) style = etree.parse(style_filename) - if is_file: - document = WLDocument.from_file(input, True, \ - parse_dublincore=parse_dublincore) - else: - document = WLDocument.from_string(input, True, \ - parse_dublincore=parse_dublincore) + document = copy.deepcopy(wldoc) + del wldoc + document.swap_endlines() if flags: for flag in flags: @@ -55,6 +50,8 @@ def transform(input, output_filename=None, is_file=True, \ document.clean_ed_note() + if not options: + options = {} result = document.transform(style, **options) del document # no longer needed large object :) @@ -62,16 +59,10 @@ def transform(input, output_filename=None, is_file=True, \ add_anchors(result.getroot()) add_table_of_contents(result.getroot()) - if output_filename is not None: - result.write(output_filename, method='html', xml_declaration=False, pretty_print=True, encoding='utf-8') - else: - return result - return True + return OutputFile.from_string(etree.tostring(result, method='html', + xml_declaration=False, pretty_print=True, encoding='utf-8')) else: - if output_filename is not None: - return False - else: - return "" + return None except KeyError: raise ValueError("'%s' is not a valid stylesheet.") except (XMLSyntaxError, XSLTApplyError), e: @@ -126,7 +117,13 @@ def extract_fragments(input_filename): open_fragments = {} closed_fragments = {} - for event, element in etree.iterparse(input_filename, events=('start', 'end')): + # iterparse would die on a HTML document + parser = etree.HTMLParser(encoding='utf-8') + buf = cStringIO.StringIO() + buf.write(etree.tostring(etree.parse(input_filename, parser).getroot()[0][0], encoding='utf-8')) + buf.seek(0) + + for event, element in etree.iterparse(buf, events=('start', 'end')): # Process begin and end elements if element.get('class', '') in ('theme-begin', 'theme-end'): if not event == 'end': continue # Process elements only once, on end event @@ -231,10 +228,12 @@ def add_table_of_contents(root): if any_ancestor(element, lambda e: e.get('id') in ('footnotes',) or e.get('class') in ('person-list',)): continue + element_text = etree.tostring(element, method='text', + encoding=unicode).strip() if element.tag == 'h3' and len(sections) and sections[-1][1] == 'h2': - sections[-1][3].append((counter, element.tag, ''.join(element.xpath('text()')), [])) + sections[-1][3].append((counter, element.tag, element_text, [])) else: - sections.append((counter, element.tag, ''.join(element.xpath('text()')), [])) + sections.append((counter, element.tag, element_text, [])) add_anchor(element, "s%d" % counter, with_link=False) counter += 1 @@ -256,3 +255,17 @@ def add_table_of_contents(root): root.insert(0, toc) + +def extract_annotations(html_path): + """For each annotation, yields a tuple: anchor, text, html.""" + parser = etree.HTMLParser(encoding='utf-8') + tree = etree.parse(html_path, parser) + footnotes = tree.find('//*[@id="footnotes"]') + if footnotes is not None: + for footnote in footnotes.findall('div'): + anchor = footnote.find('a[@name]').get('name') + del footnote[:2] + text_str = etree.tostring(footnote, method='text', encoding='utf-8').strip() + html_str = etree.tostring(footnote, method='html', encoding='utf-8') + yield anchor, text_str, html_str +