示例#1
0
文件: survey.py 项目: gushil/pyxform
    def _generate_static_instances(list_name, choice_list):
        """
        Generates <instance> elements for static data
        (e.g. choices for select type questions)

        Note that per commit message 0578242 and in xls2json.py R539, an
        instance is only output for select items defined in the choices sheet
        when the item has a choice_filter, and it is that way for backwards
        compatibility.
        """
        instance_element_list = []
        multi_language = isinstance(choice_list[0].get("label"), dict)
        has_media = bool(choice_list[0].get("media"))

        for idx, choice in enumerate(choice_list):
            choice_element_list = []
            # Add a unique id to the choice element in case there is itext
            # it references
            if (
                multi_language
                or has_media
                or has_dynamic_label(choice_list, multi_language)
            ):
                itext_id = "-".join([list_name, str(idx)])
                choice_element_list.append(node("itextId", itext_id))

            for name, value in sorted(choice.items()):
                if isinstance(value, basestring) and name != "label":
                    choice_element_list.append(node(name, unicode(value)))
                if (
                    not multi_language
                    and not has_media
                    and not has_dynamic_label(choice_list, multi_language)
                    and isinstance(value, basestring)
                    and name == "label"
                ):
                    choice_element_list.append(node(name, unicode(value)))

            instance_element_list.append(node("item", *choice_element_list))

        return InstanceInfo(
            type="choice",
            context="survey",
            name=list_name,
            src=None,
            instance=node(
                "instance", node("root", *instance_element_list), id=list_name
            ),
        )
示例#2
0
文件: survey.py 项目: gushil/pyxform
    def _setup_translations(self):
        """
        set up the self._translations dict which will be referenced in the
        setup media and itext functions
        """

        def _setup_choice_translations(name, choice_value, itext_id):
            for media_type_or_language, value in choice_value.items():  # noqa
                if isinstance(value, dict):
                    for language, val in value.items():
                        self._add_to_nested_dict(
                            self._translations,
                            [language, itext_id, media_type_or_language],
                            val,
                        )
                else:
                    if name == "media":
                        self._add_to_nested_dict(
                            self._translations,
                            [self.default_language, itext_id, media_type_or_language],
                            value,
                        )
                    else:
                        self._add_to_nested_dict(
                            self._translations,
                            [media_type_or_language, itext_id, "long"],
                            value,
                        )

        self._translations = defaultdict(dict)  # pylint: disable=W0201
        for element in self.iter_descendants():
            # Skip creation of translations for choices in filtered selects
            # The creation of these translations is done futher below in this
            # function
            parent = element.get("parent")
            if parent and not parent.get("choice_filter"):
                for d in element.get_translations(self.default_language):
                    translation_path = d["path"]
                    form = "long"

                    if "guidance_hint" in d["path"]:
                        translation_path = d["path"].replace("guidance_hint", "hint")
                        form = "guidance"

                    self._translations[d["lang"]][
                        translation_path
                    ] = self._translations[d["lang"]].get(translation_path, {})

                    self._translations[d["lang"]][translation_path].update(
                        {
                            form: {
                                "text": d["text"],
                                "output_context": d["output_context"],
                            }
                        }
                    )

        # This code sets up translations for choices in filtered selects.
        for list_name, choice_list in self.choices.items():
            multi_language = isinstance(choice_list[0].get("label"), dict)
            has_media = bool(choice_list[0].get("media"))
            if (
                not multi_language
                and not has_media
                and not has_dynamic_label(choice_list, multi_language)
            ):
                continue
            for idx, choice in zip(range(len(choice_list)), choice_list):
                for name, choice_value in choice.items():
                    itext_id = "-".join([list_name, str(idx)])
                    if isinstance(choice_value, dict):
                        _setup_choice_translations(name, choice_value, itext_id)
                    elif name == "label":
                        self._add_to_nested_dict(
                            self._translations,
                            [self.default_language, itext_id, "long"],
                            choice_value,
                        )
示例#3
0
    def build_xml(self):
        assert self.bind["type"] in ["string", "odk:rank"]
        survey = self.get_root()
        control_dict = self.control.copy()
        # Resolve field references in attributes
        for key, value in control_dict.items():
            control_dict[key] = survey.insert_xpaths(value, self)
        control_dict["ref"] = self.get_xpath()

        result = node(**control_dict)
        for element in self.xml_label_and_hint():
            result.appendChild(element)

        choices = survey.get("choices")
        multi_language = False
        if choices is not None and len(choices) > 0:
            first_choices = next(iter(choices.values()))
            multi_language = isinstance(first_choices[0].get("label"), dict)

        # itemset are only supposed to be strings,
        # check to prevent the rare dicts that show up
        if self["itemset"] and isinstance(self["itemset"], str):
            choice_filter = self.get("choice_filter")

            itemset, file_extension = os.path.splitext(self["itemset"])
            itemset_value_ref = self.parameters.get(
                "value",
                EXTERNAL_CHOICES_ITEMSET_REF_VALUE_GEOJSON if file_extension
                == ".geojson" else EXTERNAL_CHOICES_ITEMSET_REF_VALUE,
            )
            itemset_label_ref = self.parameters.get(
                "label",
                EXTERNAL_CHOICES_ITEMSET_REF_LABEL_GEOJSON if file_extension
                == ".geojson" else EXTERNAL_CHOICES_ITEMSET_REF_LABEL,
            )

            has_media = False
            has_dyn_label = False
            is_previous_question = bool(
                re.match(r"^\${.*}$", self.get("itemset")))

            if choices.get(itemset):
                has_media = bool(choices[itemset][0].get("media"))
                has_dyn_label = has_dynamic_label(choices[itemset],
                                                  multi_language)

            if file_extension in EXTERNAL_INSTANCE_EXTENSIONS:
                itemset = itemset
            else:
                if not multi_language and not has_media and not has_dyn_label:
                    itemset = self["itemset"]
                else:
                    itemset = self["itemset"]
                    itemset_label_ref = "jr:itext(itextId)"

            choice_filter = survey.insert_xpaths(choice_filter, self, True,
                                                 is_previous_question)
            if is_previous_question:
                path = (survey.insert_xpaths(
                    self["itemset"], self,
                    reference_parent=True).strip().split("/"))
                nodeset = "/".join(path[:-1])
                itemset_value_ref = path[-1]
                itemset_label_ref = path[-1]
                if choice_filter:
                    choice_filter = choice_filter.replace(
                        "current()/" + nodeset, ".").replace(nodeset, ".")
                else:
                    # Choices must have a value. Filter out repeat instances without
                    # an answer for the linked question
                    name = path[-1]
                    choice_filter = f"./{name} != ''"
            else:
                nodeset = "instance('" + itemset + "')/root/item"

            if choice_filter:
                nodeset += "[" + choice_filter + "]"

            if self["parameters"]:
                params = self["parameters"]

                if "randomize" in params and params["randomize"] == "true":
                    nodeset = "randomize(" + nodeset

                    if "seed" in params:
                        if params["seed"].startswith("${"):
                            nodeset = (nodeset + ", " + survey.insert_xpaths(
                                params["seed"], self).strip())
                        else:
                            nodeset = nodeset + ", " + params["seed"]

                    nodeset += ")"

            itemset_children = [
                node("value", ref=itemset_value_ref),
                node("label", ref=itemset_label_ref),
            ]
            result.appendChild(
                node("itemset", *itemset_children, nodeset=nodeset))
        else:
            for child in self.children:
                result.appendChild(child.xml())

        return result