aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS4
-rw-r--r--mammoth/docx/styles_xml.py13
-rw-r--r--tests/docx/styles_xml_tests.py12
3 files changed, 28 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index 9d89eb5..41a48cb 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,7 @@
+# 1.11.0
+
+* Ignore style definitions using a style ID that has already been used.
+
# 1.10.0
* Add "Heading" and "Body" styles, as found in documents created by Apple Pages,
diff --git a/mammoth/docx/styles_xml.py b/mammoth/docx/styles_xml.py
index 0b3f39d..3178553 100644
--- a/mammoth/docx/styles_xml.py
+++ b/mammoth/docx/styles_xml.py
@@ -67,7 +67,18 @@ def read_styles_xml_element(element):
style = _read_style_element(style_element)
style_set = styles.get(element_type)
- if style_set is not None:
+
+ # Per 17.7.4.17 style (Style Definition) of ECMA-376 4th edition Part 1:
+ #
+ # > If multiple style definitions each declare the same value for their
+ # > styleId, then the first such instance shall keep its current
+ # > identifier with all other instances being reassigned in any manner
+ # > desired.
+ #
+ # For the purpose of conversion, there's no point holding onto styles
+ # with reassigned style IDs, so we ignore such style definitions.
+
+ if style_set is not None and style.style_id not in style_set:
style_set[style.style_id] = style
return Styles(
diff --git a/tests/docx/styles_xml_tests.py b/tests/docx/styles_xml_tests.py
index 165d86c..008e12f 100644
--- a/tests/docx/styles_xml_tests.py
+++ b/tests/docx/styles_xml_tests.py
@@ -101,6 +101,18 @@ def test_numbering_style_has_num_id_read_from_paragraph_properties():
assert_equal("42", styles.find_numbering_style_by_id("List1").num_id)
+def test_when_multiple_style_elements_have_same_style_id_then_only_first_element_is_used():
+ element = xml_element("w:styles", {}, [
+ _table_style_element("TableNormal", "Normal Table"),
+ _table_style_element("TableNormal", "Table Normal"),
+ ])
+ styles = read_styles_xml_element(element)
+ assert_equal(
+ "Normal Table",
+ styles.find_table_style_by_id("TableNormal").name
+ )
+
+
def _paragraph_style_element(style_id, name):
return _style_element("paragraph", style_id, name)