From 2af622a449867a2491eb3198423101a6e98485b5 Mon Sep 17 00:00:00 2001 From: Dickson Ukang'a Date: Tue, 3 Apr 2018 12:57:31 +0300 Subject: [PATCH] Use relative references for repeats only. Fix #4 --- pyxform/survey.py | 18 +++++++++++ pyxform/tests_v1/test_repeat.py | 57 +++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 pyxform/tests_v1/test_repeat.py diff --git a/pyxform/survey.py b/pyxform/survey.py index 40583ae33..7f293b771 100644 --- a/pyxform/survey.py +++ b/pyxform/survey.py @@ -29,6 +29,21 @@ def register_nsmap(): register_nsmap() +def is_parent_a_repeat(survey, xpath): + """ + Given a survey object and an xpath returns True if any parent is a repeat. + """ + parent_xpath = '/'.join(xpath.split('/')[:-1]) + if not parent_xpath: + return False + + repeats = [ + item for item in survey.iter_descendants() + if item.get_xpath() == parent_xpath and item.type == 'repeat'] + + return any(repeats) or is_parent_a_repeat(survey, parent_xpath) + + class Survey(Section): FIELDS = Section.FIELDS.copy() @@ -626,6 +641,9 @@ def _var_repl_function(self, matchobj): if self._xpath[name] is None: raise PyXFormError(intro + " There are multiple survey elements" " with this name.") + # is parent a repeat? + if is_parent_a_repeat(self, self._xpath[name]): + return " current()/../" + name + " " return " " + self._xpath[name] + " " diff --git a/pyxform/tests_v1/test_repeat.py b/pyxform/tests_v1/test_repeat.py new file mode 100644 index 000000000..635239b5b --- /dev/null +++ b/pyxform/tests_v1/test_repeat.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +""" +test_repeat.py +""" +from pyxform.tests_v1.pyxform_test_case import PyxformTestCase + + +class TestRepeat(PyxformTestCase): + """ + TestRepeat class. + """ + def test_repeat_relative_reference(self): + """ + Test relative reference in repeats. + """ + self.assertPyxformXform( + debug=True, + name="test_repeat", + md=""" + | survey | | | | | + | | type | name | relevant | label | + | | text | Z | | Fruit | + | | begin repeat | section | | Section | + | | text | A | | A | + | | text | B | ${A}='oat' | B w ${A} | + | | end repeat | | | | + | | begin repeat | section2 | | Section 2 | + | | text | C | | C | + | | begin group | sectiona | | Section A | + | | text | D | | D | + | | text | E | ${D}='oat' | E w ${Z} | + | | end group | | | | + | | end repeat | | | | + """, + instance__contains=[ + '
', + '', + '', + '
', + ], + model__contains=[ + """""", + """""", + """""" + ], + xml__contains=[ + '', + '', + '', + """""", + """""" + ], + )