From f37fce68a77630a199737959e9d235d0a1263662 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sun, 8 Jun 2014 22:25:35 +0100 Subject: Read style name for paragraphs out of source document --- mammoth/docx/__init__.py | 5 +++++ mammoth/docx/document_xml.py | 19 ++++++++++++++++--- mammoth/docx/styles_xml.py | 10 ++++++---- tests/docx/document_xml_tests.py | 17 ++++++++++++++++- 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/mammoth/docx/__init__.py b/mammoth/docx/__init__.py index 41c42a8..c0a7ea3 100644 --- a/mammoth/docx/__init__.py +++ b/mammoth/docx/__init__.py @@ -7,6 +7,7 @@ from .document_xml import read_document_xml_element from .content_types_xml import read_content_types_xml_element from .relationships_xml import read_relationships_xml_element from .numbering_xml import read_numbering_xml_element, Numbering +from .styles_xml import read_styles_xml_element _namespaces = [ @@ -34,6 +35,9 @@ def read(fileobj): else: numbering = Numbering({}) + with _open_entry(zip_file, "word/styles.xml") as styles_fileobj: + styles = read_styles_xml_element(_parse_docx_xml(styles_fileobj)) + with _open_entry(zip_file, "word/document.xml") as document_fileobj: document_xml = _parse_docx_xml(document_fileobj) return read_document_xml_element( @@ -42,6 +46,7 @@ def read(fileobj): relationships=relationships, docx_file=zip_file, numbering=numbering, + styles=styles, ) diff --git a/mammoth/docx/document_xml.py b/mammoth/docx/document_xml.py index 5023ec5..83d82df 100644 --- a/mammoth/docx/document_xml.py +++ b/mammoth/docx/document_xml.py @@ -7,11 +7,17 @@ from .. import lists from .xmlparser import node_types -def read_document_xml_element(element, numbering=None, content_types=None, relationships=None, docx_file=None): - reader = _create_reader(numbering=numbering, content_types=content_types, relationships=relationships, docx_file=docx_file) +def read_document_xml_element(element, numbering=None, content_types=None, relationships=None, styles=None, docx_file=None): + reader = _create_reader( + numbering=numbering, + content_types=content_types, + relationships=relationships, + styles=styles, + docx_file=docx_file, + ) return reader(element) -def _create_reader(numbering, content_types, relationships, docx_file): +def _create_reader(numbering, content_types, relationships, styles, docx_file): _handlers = {} _ignored_elements = set([ "w:bookmarkStart", @@ -63,6 +69,12 @@ def _create_reader(numbering, content_types, relationships, docx_file): style_id = properties \ .find_child_or_null("w:pStyle") \ .attributes.get("w:val") + + if style_id is None: + style_name = None + else: + style_name = styles.find_paragraph_style_by_id(style_id).name + numbering_properties = properties.find_child("w:numPr") if numbering_properties is None: numbering = None @@ -73,6 +85,7 @@ def _create_reader(numbering, content_types, relationships, docx_file): .map(lambda children: documents.paragraph( children=children, style_id=style_id, + style_name=style_name, numbering=numbering, )) diff --git a/mammoth/docx/styles_xml.py b/mammoth/docx/styles_xml.py index c220740..ab3cc0f 100644 --- a/mammoth/docx/styles_xml.py +++ b/mammoth/docx/styles_xml.py @@ -23,16 +23,18 @@ def read_styles_xml_element(element): for style_element in element.find_children("w:style"): style = _read_style_element(style_element) - styles[style.element_type][style.style_id] = style + element_type = style_element.attributes["w:type"] + style_set = styles.get(element_type) + if style_set is not None: + style_set[style.style_id] = style return Styles(paragraph_styles, character_styles) def _read_style_element(element): - element_type = element.attributes["w:type"] style_id = element.attributes["w:styleId"] name = element.find_child("w:name").attributes["w:val"] - return Style(element_type=element_type, style_id=style_id, name=name) + return Style(style_id=style_id, name=name) -Style = collections.namedtuple("Style", ["element_type", "style_id", "name"]) +Style = collections.namedtuple("Style", ["style_id", "name"]) diff --git a/tests/docx/document_xml_tests.py b/tests/docx/document_xml_tests.py index e63cd60..e8757f5 100644 --- a/tests/docx/document_xml_tests.py +++ b/tests/docx/document_xml_tests.py @@ -8,6 +8,7 @@ from mammoth.docx.xmlparser import element as xml_element, text as xml_text from mammoth.docx.document_xml import read_document_xml_element from mammoth.docx.numbering_xml import Numbering from mammoth.docx.relationships_xml import Relationships, Relationship +from mammoth.docx.styles_xml import Styles, Style @istest @@ -51,9 +52,23 @@ class ReadXmlElementTests(object): 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_and_get_document_xml_element(paragraph_xml) + + styles = Styles({"Heading1": Style(style_id="Heading1", name="Heading 1")}, {}) + + paragraph = _read_and_get_document_xml_element(paragraph_xml, styles=styles) assert_equal("Heading1", paragraph.style_id) + @istest + def paragraph_has_style_name_read_from_paragraph_properties_and_styles(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]) + + styles = Styles({"Heading1": Style(style_id="Heading1", name="Heading 1")}, {}) + + paragraph = _read_and_get_document_xml_element(paragraph_xml, styles=styles) + assert_equal("Heading 1", paragraph.style_name) + @istest def paragraph_has_no_numbering_if_it_has_no_numbering_properties(self): element = xml_element("w:p") -- cgit v1.2.3