Skip to content

Commit 7c58744

Browse files
committed
Convert SDT checkboxes to checkbox inputs
1 parent 6448068 commit 7c58744

File tree

4 files changed

+61
-2
lines changed

4 files changed

+61
-2
lines changed

NEWS

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# 1.9.0
2+
3+
* Detect checkboxes, both as complex fields and structured document tags, and
4+
convert them to checkbox inputs.
5+
16
# 1.8.0
27

38
* Add style mapping for highlights.

mammoth/docx/body_xml.py

+15-2
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,10 @@ def read_boolean_element(element):
137137
if element is None:
138138
return False
139139
else:
140-
return element.attributes.get("w:val") not in ["false", "0"]
140+
return read_boolean_attribute_value(element.attributes.get("w:val"))
141+
142+
def read_boolean_attribute_value(value):
143+
return value not in ["false", "0"]
141144

142145
def read_underline_element(element):
143146
return element and element.attributes.get("w:val") not in [None, "false", "0", "none"]
@@ -569,7 +572,17 @@ def alternate_content(element):
569572
return read_child_elements(element.find_child("mc:Fallback"))
570573

571574
def read_sdt(element):
572-
return read_child_elements(element.find_child_or_null("w:sdtContent"))
575+
checkbox = element.find_child_or_null("w:sdtPr").find_child("wordml:checkbox")
576+
577+
if checkbox is not None:
578+
checked_element = checkbox.find_child("wordml:checked")
579+
is_checked = (
580+
checked_element is not None and
581+
read_boolean_attribute_value(checked_element.attributes.get("wordml:val"))
582+
)
583+
return _success(documents.checkbox(checked=is_checked))
584+
else:
585+
return read_child_elements(element.find_child_or_null("w:sdtContent"))
573586

574587
handlers = {
575588
"w:t": text,

mammoth/docx/office_xml.py

+4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
("mc", "http://schemas.openxmlformats.org/markup-compatibility/2006"),
2424
("v", "urn:schemas-microsoft-com:vml"),
2525
("office-word", "urn:schemas-microsoft-com:office:word"),
26+
27+
# [MS-DOCX]: Word Extensions to the Office Open XML (.docx) File Format
28+
# https://learn.microsoft.com/en-us/openspecs/office_standards/ms-docx/b839fe1f-e1ca-4fa6-8c26-5954d0abbccd
29+
("wordml", "http://schemas.microsoft.com/office/word/2010/wordml"),
2630
]
2731

2832

tests/docx/body_xml_tests.py

+37
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,43 @@ def test_complex_field_checkbox_with_default_0_and_checked_1_is_checked(self):
751751
is_run(children=is_sequence(is_checkbox(checked=True))),
752752
)))
753753

754+
def test_structured_document_tag_checkbox_without_checked_is_not_checked(self):
755+
element = xml_element("w:sdt", {}, [
756+
xml_element("w:sdtPr", {}, [
757+
xml_element("wordml:checkbox"),
758+
]),
759+
])
760+
761+
result = _read_and_get_document_xml_element(element)
762+
763+
assert_that(result, is_checkbox(checked=False))
764+
765+
def test_structured_document_tag_checkbox_with_checked_0_is_not_checked(self):
766+
element = xml_element("w:sdt", {}, [
767+
xml_element("w:sdtPr", {}, [
768+
xml_element("wordml:checkbox", {}, [
769+
xml_element("wordml:checked", {"wordml:val": "0"}),
770+
]),
771+
]),
772+
])
773+
774+
result = _read_and_get_document_xml_element(element)
775+
776+
assert_that(result, is_checkbox(checked=False))
777+
778+
def test_structured_document_tag_checkbox_with_checked_1_is_checked(self):
779+
element = xml_element("w:sdt", {}, [
780+
xml_element("w:sdtPr", {}, [
781+
xml_element("wordml:checkbox", {}, [
782+
xml_element("wordml:checked", {"wordml:val": "1"}),
783+
]),
784+
]),
785+
])
786+
787+
result = _read_and_get_document_xml_element(element)
788+
789+
assert_that(result, is_checkbox(checked=True))
790+
754791
def _complex_field_checkbox_paragraph(self, ff_data_children):
755792
return xml_element("w:p", {}, [
756793
xml_element("w:r", {}, [

0 commit comments

Comments
 (0)