aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mammoth/docx/__init__.py73
-rw-r--r--mammoth/docx/document_xml.py76
-rw-r--r--tests/docx/document_xml_tests.py82
-rw-r--r--tests/docx/docx_tests.py78
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)])
-