Skip to content

Commit

Permalink
Read whether complex field checkbox is checked
Browse files Browse the repository at this point in the history
  • Loading branch information
mwilliamson committed Nov 30, 2024
1 parent e04c8ee commit 237d861
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 2 deletions.
17 changes: 15 additions & 2 deletions mammoth/docx/body_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,10 @@ def _read_run_style(properties):
return _read_style(properties, "w:rStyle", "Run", styles.find_character_style_by_id)

def read_boolean_element(element):
return element and element.attributes.get("w:val") not in ["false", "0"]
if element is None:
return False
else:
return element.attributes.get("w:val") not in ["false", "0"]

def read_underline_element(element):
return element and element.attributes.get("w:val") not in [None, "false", "0", "none"]
Expand Down Expand Up @@ -231,7 +234,17 @@ def parse_instr_text(instr_text, *, fld_char):

checkbox_result = re.match(r'\s*FORMCHECKBOX\s*', instr_text)
if checkbox_result is not None:
return complex_fields.checkbox(checked=False)
checkbox_element = fld_char \
.find_child_or_null("w:ffData") \
.find_child_or_null("w:checkBox")
checked_element = checkbox_element.find_child("w:checked")

if checked_element is None:
checked = read_boolean_element(checkbox_element.find_child("w:default"))
else:
checked = read_boolean_element(checked_element)

return complex_fields.checkbox(checked=checked)

return None

Expand Down
93 changes: 93 additions & 0 deletions tests/docx/body_xml_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,99 @@ def test_complex_field_checkbox_with_separate_is_read(self):
is_run(children=is_sequence(is_checkbox())),
)))

def test_complex_field_checkbox_without_default_nor_checked_is_unchecked(self):
element = self._complex_field_checkbox_paragraph([
xml_element("w:checkBox"),
])

paragraph = _read_and_get_document_xml_element(element);

assert_that(paragraph, is_paragraph(children=is_sequence(
is_empty_run,
is_empty_run,
is_run(children=is_sequence(is_checkbox(checked=False))),
)))

def test_complex_field_checkbox_with_default_0_and_without_checked_is_unchecked(self):
element = self._complex_field_checkbox_paragraph([
xml_element("w:checkBox", {}, [
xml_element("w:default", {"w:val": "0"}),
]),
])

paragraph = _read_and_get_document_xml_element(element);

assert_that(paragraph, is_paragraph(children=is_sequence(
is_empty_run,
is_empty_run,
is_run(children=is_sequence(is_checkbox(checked=False))),
)))

def test_complex_field_checkbox_with_default_1_and_without_checked_is_checked(self):
element = self._complex_field_checkbox_paragraph([
xml_element("w:checkBox", {}, [
xml_element("w:default", {"w:val": "1"}),
]),
])

paragraph = _read_and_get_document_xml_element(element);

assert_that(paragraph, is_paragraph(children=is_sequence(
is_empty_run,
is_empty_run,
is_run(children=is_sequence(is_checkbox(checked=True))),
)))

def test_complex_field_checkbox_with_default_1_and_checked_0_is_unchecked(self):
element = self._complex_field_checkbox_paragraph([
xml_element("w:checkBox", {}, [
xml_element("w:default", {"w:val": "1"}),
xml_element("w:checked", {"w:val": "0"}),
]),
])

paragraph = _read_and_get_document_xml_element(element);

assert_that(paragraph, is_paragraph(children=is_sequence(
is_empty_run,
is_empty_run,
is_run(children=is_sequence(is_checkbox(checked=False))),
)))

def test_complex_field_checkbox_with_default_0_and_checked_1_is_checked(self):
element = self._complex_field_checkbox_paragraph([
xml_element("w:checkBox", {}, [
xml_element("w:default", {"w:val": "0"}),
xml_element("w:checked", {"w:val": "1"}),
]),
])

paragraph = _read_and_get_document_xml_element(element);

assert_that(paragraph, is_paragraph(children=is_sequence(
is_empty_run,
is_empty_run,
is_run(children=is_sequence(is_checkbox(checked=True))),
)))

def _complex_field_checkbox_paragraph(self, ff_data_children):
return xml_element("w:p", {}, [
xml_element("w:r", {}, [
xml_element("w:fldChar", {"w:fldCharType": "begin"}, [
xml_element("w:ffData", {}, ff_data_children)
]),
]),
xml_element("w:instrText", {}, [
xml_text(' FORMCHECKBOX ')
]),
xml_element("w:r", {}, [
xml_element("w:fldChar", {"w:fldCharType": "separate"})
]),
xml_element("w:r", {}, [
xml_element("w:fldChar", {"w:fldCharType": "end"})
]),
])


def test_can_read_tab_element():
element = xml_element("w:tab")
Expand Down

0 comments on commit 237d861

Please sign in to comment.