diff options
| author | Michael Williamson <mike@zwobble.org> | 2013-12-01 11:51:38 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2013-12-01 11:51:38 +0000 |
| commit | d5acaf1071564a9997a330315ea99cdc1017bae7 (patch) | |
| tree | ffaee2557ff0fd4a2c69c19855293faa29b1277f | |
| parent | f8d72dbba832db282a3ec04a5108fbd090f49a4f (diff) | |
Move document.xml parsing to separate module
| -rw-r--r-- | mammoth/docx/__init__.py | 73 | ||||
| -rw-r--r-- | mammoth/docx/document_xml.py | 76 | ||||
| -rw-r--r-- | tests/docx/document_xml_tests.py | 82 | ||||
| -rw-r--r-- | tests/docx/docx_tests.py | 78 |
4 files changed, 161 insertions, 148 deletions
diff --git a/mammoth/docx/__init__.py b/mammoth/docx/__init__.py index de2b8a8..17c90a8 100644 --- a/mammoth/docx/__init__.py +++ b/mammoth/docx/__init__.py @@ -3,6 +3,7 @@ import zipfile from .. import documents from ..results import Result from .xmlparser import parse_xml, node_types +from .document_xml import read_document_xml_element _namespaces = [ @@ -14,75 +15,5 @@ def read(fileobj): zip_file = zipfile.ZipFile(fileobj) document_fileobj = zip_file.open("word/document.xml") document_xml = parse_xml(document_fileobj, _namespaces) - return Result(read_xml_element(document_xml), []) + return Result(read_document_xml_element(document_xml), []) - -_handlers = {} - - -def handler(name): - def add(func): - _handlers[name] = func - - return add - - -def read_xml_element(element): - handler = _handlers.get(element.name) - if handler is None: - return None - else: - return handler(element) - - -@handler("w:t") -def text(element): - return documents.Text(_inner_text(element)) - - -@handler("w:r") -def run(element): - return documents.Run(_read_xml_elements(element.children)) - - -@handler("w:p") -def paragraph(element): - properties = element.find_child_or_null("w:pPr") - style_name = properties \ - .find_child_or_null("w:pStyle") \ - .attributes.get("w:val") - - children = _read_xml_elements(element.children) - return documents.paragraph(children, style_name) - - -@handler("w:body") -def body(element): - return _read_xml_elements(element.children) - - -@handler("w:document") -def document(element): - body_element = _find_child(element, "w:body") - return documents.Document(_read_xml_elements(body_element.children)) - - -def _find(predicate, iterable): - for item in iterable: - if predicate(item): - return item - - -def _find_child(element, name): - return _find(lambda child: child.name == name, element.children) - - -def _read_xml_elements(elements): - return filter(None, map(read_xml_element, elements)) - - -def _inner_text(node): - if node.node_type == node_types.text: - return node.value - else: - return "".join(_inner_text(child) for child in node.children) diff --git a/mammoth/docx/document_xml.py b/mammoth/docx/document_xml.py new file mode 100644 index 0000000..c83c28c --- /dev/null +++ b/mammoth/docx/document_xml.py @@ -0,0 +1,76 @@ +import zipfile + +from .. import documents +from ..results import Result +from .xmlparser import parse_xml, node_types + + +_handlers = {} + + +def handler(name): + def add(func): + _handlers[name] = func + + return add + + +def read_document_xml_element(element): + handler = _handlers.get(element.name) + if handler is None: + return None + else: + return handler(element) + + +@handler("w:t") +def text(element): + return documents.Text(_inner_text(element)) + + +@handler("w:r") +def run(element): + return documents.Run(_read_xml_elements(element.children)) + + +@handler("w:p") +def paragraph(element): + properties = element.find_child_or_null("w:pPr") + style_name = properties \ + .find_child_or_null("w:pStyle") \ + .attributes.get("w:val") + + children = _read_xml_elements(element.children) + return documents.paragraph(children, style_name) + + +@handler("w:body") +def body(element): + return _read_xml_elements(element.children) + + +@handler("w:document") +def document(element): + body_element = _find_child(element, "w:body") + return documents.Document(_read_xml_elements(body_element.children)) + + +def _find(predicate, iterable): + for item in iterable: + if predicate(item): + return item + + +def _find_child(element, name): + return _find(lambda child: child.name == name, element.children) + + +def _read_xml_elements(elements): + return filter(None, map(read_document_xml_element, elements)) + + +def _inner_text(node): + if node.node_type == node_types.text: + return node.value + else: + return "".join(_inner_text(child) for child in node.children) diff --git a/tests/docx/document_xml_tests.py b/tests/docx/document_xml_tests.py new file mode 100644 index 0000000..2771e2c --- /dev/null +++ b/tests/docx/document_xml_tests.py @@ -0,0 +1,82 @@ +from nose.tools import istest, assert_equal + +from mammoth import docx, documents +from mammoth.docx.xmlparser import element as xml_element, text as xml_text +from mammoth.docx.document_xml import read_document_xml_element + + +@istest +class ReadXmlElementTests(object): + @istest + def text_from_text_element_is_read(self): + element = _text_element("Hello!") + assert_equal(documents.Text("Hello!"), read_document_xml_element(element)) + + @istest + def can_read_text_within_run(self): + element = _run_element_with_text("Hello!") + assert_equal( + documents.Run([documents.Text("Hello!")]), + read_document_xml_element(element) + ) + + @istest + def can_read_text_within_paragraph(self): + element = _paragraph_element_with_text("Hello!") + assert_equal( + documents.paragraph([documents.Run([documents.Text("Hello!")])]), + read_document_xml_element(element) + ) + + @istest + def can_read_text_within_document(self): + element = _document_element_with_text("Hello!") + assert_equal( + documents.Document([documents.paragraph([documents.Run([documents.Text("Hello!")])])]), + read_document_xml_element(element) + ) + + @istest + def paragraph_has_no_style_if_it_has_no_properties(self): + element = xml_element("w:p") + assert_equal(None, read_document_xml_element(element).style_name) + + @istest + def paragraph_has_style_name_read_from_paragraph_properties_if_present(self): + style_xml = xml_element("w:pStyle", {"w:val": "Heading1"}) + properties_xml = xml_element("w:pPr", {}, [style_xml]) + paragraph_xml = xml_element("w:p", {}, [properties_xml]) + paragraph = read_document_xml_element(paragraph_xml) + assert_equal("Heading1", paragraph.style_name) + + @istest + def unrecognised_elements_are_ignored(self): + element = xml_element("w:huh", {}, []) + assert_equal(None, read_document_xml_element(element)) + + @istest + def unrecognised_children_are_ignored(self): + element = xml_element("w:r", {}, [_text_element("Hello!"), xml_element("w:huh", {}, [])]) + assert_equal( + documents.Run([documents.Text("Hello!")]), + read_document_xml_element(element) + ) + + +def _document_element_with_text(text): + return xml_element("w:document", {}, [ + xml_element("w:body", {}, [_paragraph_element_with_text(text)]) + ]) + + +def _paragraph_element_with_text(text): + return xml_element("w:p", {}, [_run_element_with_text(text)]) + + +def _run_element_with_text(text): + return xml_element("w:r", {}, [_text_element(text)]) + + +def _text_element(value): + return xml_element("w:t", {}, [xml_text(value)]) + diff --git a/tests/docx/docx_tests.py b/tests/docx/docx_tests.py index 9e9efe2..39895cb 100644 --- a/tests/docx/docx_tests.py +++ b/tests/docx/docx_tests.py @@ -4,6 +4,7 @@ from mammoth import docx, documents from mammoth.docx.xmlparser import element as xml_element, text as xml_text from ..testing import test_path + @istest class ReadTests(object): @istest @@ -18,80 +19,3 @@ class ReadTests(object): ]) ]) assert_equal(expected_document, result.value) - - -@istest -class ReadXmlElementTests(object): - @istest - def text_from_text_element_is_read(self): - element = _text_element("Hello!") - assert_equal(documents.Text("Hello!"), docx.read_xml_element(element)) - - @istest - def can_read_text_within_run(self): - element = _run_element_with_text("Hello!") - assert_equal( - documents.Run([documents.Text("Hello!")]), - docx.read_xml_element(element) - ) - - @istest - def can_read_text_within_paragraph(self): - element = _paragraph_element_with_text("Hello!") - assert_equal( - documents.paragraph([documents.Run([documents.Text("Hello!")])]), - docx.read_xml_element(element) - ) - - @istest - def can_read_text_within_document(self): - element = _document_element_with_text("Hello!") - assert_equal( - documents.Document([documents.paragraph([documents.Run([documents.Text("Hello!")])])]), - docx.read_xml_element(element) - ) - - @istest - def paragraph_has_no_style_if_it_has_no_properties(self): - element = xml_element("w:p") - assert_equal(None, docx.read_xml_element(element).style_name) - - @istest - def paragraph_has_style_name_read_from_paragraph_properties_if_present(self): - style_xml = xml_element("w:pStyle", {"w:val": "Heading1"}) - properties_xml = xml_element("w:pPr", {}, [style_xml]) - paragraph_xml = xml_element("w:p", {}, [properties_xml]) - paragraph = docx.read_xml_element(paragraph_xml) - assert_equal("Heading1", paragraph.style_name) - - @istest - def unrecognised_elements_are_ignored(self): - element = xml_element("w:huh", {}, []) - assert_equal(None, docx.read_xml_element(element)) - - @istest - def unrecognised_children_are_ignored(self): - element = xml_element("w:r", {}, [_text_element("Hello!"), xml_element("w:huh", {}, [])]) - assert_equal( - documents.Run([documents.Text("Hello!")]), - docx.read_xml_element(element) - ) - - -def _document_element_with_text(text): - return xml_element("w:document", {}, [ - xml_element("w:body", {}, [_paragraph_element_with_text(text)]) - ]) - - -def _paragraph_element_with_text(text): - return xml_element("w:p", {}, [_run_element_with_text(text)]) - - -def _run_element_with_text(text): - return xml_element("w:r", {}, [_text_element(text)]) - - -def _text_element(value): - return xml_element("w:t", {}, [xml_text(value)]) - |
