def inject_instanceid(xml_str, uuid): if get_uuid_from_xml(xml_str) is None: xml = clean_and_parse_xml(xml_str) children = xml.childNodes if children.length == 0: raise ValueError(_("XML string must have a survey element.")) # check if we have a meta tag survey_node = children.item(0) meta_tags = [ n for n in survey_node.childNodes if n.nodeType == Node.ELEMENT_NODE and n.tagName.lower() == "meta"] if len(meta_tags) == 0: meta_tag = xml.createElement("meta") xml.documentElement.appendChild(meta_tag) else: meta_tag = meta_tags[0] # check if we have an instanceID tag uuid_tags = [ n for n in meta_tag.childNodes if n.nodeType == Node.ELEMENT_NODE and n.tagName == "instanceID"] if len(uuid_tags) == 0: uuid_tag = xml.createElement("instanceID") meta_tag.appendChild(uuid_tag) else: uuid_tag = uuid_tags[0] # insert meta and instanceID text_node = xml.createTextNode(u"uuid:%s" % uuid) uuid_tag.appendChild(text_node) return xml.toxml() return xml_str
def inject_instanceid(xml_str, uuid): if get_uuid_from_xml(xml_str) is None: xml = clean_and_parse_xml(xml_str) children = xml.childNodes if children.length == 0: raise ValueError(_("XML string must have a survey element.")) # check if we have a meta tag survey_node = children.item(0) meta_tags = [ n for n in survey_node.childNodes if n.nodeType == Node.ELEMENT_NODE and n.tagName.lower() == "meta" ] if len(meta_tags) == 0: meta_tag = xml.createElement("meta") xml.documentElement.appendChild(meta_tag) else: meta_tag = meta_tags[0] # check if we have an instanceID tag uuid_tags = [ n for n in meta_tag.childNodes if n.nodeType == Node.ELEMENT_NODE and n.tagName == "instanceID" ] if len(uuid_tags) == 0: uuid_tag = xml.createElement("instanceID") meta_tag.appendChild(uuid_tag) else: uuid_tag = uuid_tags[0] # insert meta and instanceID text_node = xml.createTextNode(u"uuid:%s" % uuid) uuid_tag.appendChild(text_node) return xml.toxml() return xml_str
def test_edited_submission(self): """ Test submissions that have been edited """ xml_submission_file_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "..", "fixtures", "tutorial", "instances", "tutorial_2012-06-27_11-27-53_w_uuid.xml" ) num_instances_history = InstanceHistory.objects.count() num_instances = Instance.objects.count() query_args = { 'username': self.user.username, 'id_string': self.xform.id_string, 'query': '{}', 'fields': '[]', 'sort': '[]', 'count': True } cursor = ParsedInstance.query_mongo(**query_args) num_mongo_instances = cursor[0]['count'] # make first submission self._make_submission(xml_submission_file_path) self.assertEqual(self.response.status_code, 201) self.assertEqual(Instance.objects.count(), num_instances + 1) # no new record in instances history self.assertEqual( InstanceHistory.objects.count(), num_instances_history) # check count of mongo instances after first submission cursor = ParsedInstance.query_mongo(**query_args) self.assertEqual(cursor[0]['count'], num_mongo_instances + 1) # edited submission xml_submission_file_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "..", "fixtures", "tutorial", "instances", "tutorial_2012-06-27_11-27-53_w_uuid_edited.xml" ) self._make_submission(xml_submission_file_path) self.assertEqual(self.response.status_code, 201) # we must have the same number of instances self.assertEqual(Instance.objects.count(), num_instances + 1) # should be a new record in instances history self.assertEqual( InstanceHistory.objects.count(), num_instances_history + 1) cursor = ParsedInstance.query_mongo(**query_args) self.assertEqual(cursor[0]['count'], num_mongo_instances + 1) # make sure we edited the mongo db record and NOT added a new row query_args['count'] = False cursor = ParsedInstance.query_mongo(**query_args) record = cursor[0] with open(xml_submission_file_path, "r") as f: xml_str = f.read() xml_str = clean_and_parse_xml(xml_str).toxml() edited_name = re.match(ur"^.+?<name>(.+?)</name>", xml_str).groups()[0] self.assertEqual(record['name'], edited_name)
def test_edited_submission(self): """ Test submissions that have been edited """ xml_submission_file_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "..", "fixtures", "tutorial", "instances", "tutorial_2012-06-27_11-27-53_w_uuid.xml") num_instances_history = InstanceHistory.objects.count() num_instances = Instance.objects.count() query_args = { 'username': self.user.username, 'id_string': self.xform.id_string, 'query': '{}', 'fields': '[]', 'sort': '[]', 'count': True } cursor = ParsedInstance.query_mongo(**query_args) num_mongo_instances = cursor[0]['count'] # make first submission self._make_submission(xml_submission_file_path) self.assertEqual(self.response.status_code, 201) self.assertEqual(Instance.objects.count(), num_instances + 1) # no new record in instances history self.assertEqual(InstanceHistory.objects.count(), num_instances_history) # check count of mongo instances after first submission cursor = ParsedInstance.query_mongo(**query_args) self.assertEqual(cursor[0]['count'], num_mongo_instances + 1) # edited submission xml_submission_file_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "..", "fixtures", "tutorial", "instances", "tutorial_2012-06-27_11-27-53_w_uuid_edited.xml") self._make_submission(xml_submission_file_path) self.assertEqual(self.response.status_code, 201) # we must have the same number of instances self.assertEqual(Instance.objects.count(), num_instances + 1) # should be a new record in instances history self.assertEqual(InstanceHistory.objects.count(), num_instances_history + 1) cursor = ParsedInstance.query_mongo(**query_args) self.assertEqual(cursor[0]['count'], num_mongo_instances + 1) # make sure we edited the mongo db record and NOT added a new row query_args['count'] = False cursor = ParsedInstance.query_mongo(**query_args) record = cursor[0] with open(xml_submission_file_path, "r") as f: xml_str = f.read() xml_str = clean_and_parse_xml(xml_str).toxml() edited_name = re.match(ur"^.+?<name>(.+?)</name>", xml_str).groups()[0] self.assertEqual(record['name'], edited_name)
def test_uuid_injection_in_cascading_select(self): """Test that the uuid is injected in the right instance node for forms with a cascading select""" pre_count = XForm.objects.count() xls_path = os.path.join(self.this_directory, "fixtures", "cascading_selects", "new_cascading_select.xls") file_name, file_ext = os.path.splitext(os.path.split(xls_path)[1]) self.response = MainTestCase._publish_xls_file(self, xls_path) post_count = XForm.objects.count() self.assertEqual(post_count, pre_count + 1) xform = XForm.objects.latest('date_created') # check that the uuid is within the main instance/ the one without an id attribute xml = clean_and_parse_xml(xform.xml) # check for instance nodes that are direct children of the model node model_node = xml.getElementsByTagName("model")[0] instance_nodes = [ node for node in model_node.childNodes if node.nodeType == Node.ELEMENT_NODE and node.tagName.lower() == "instance" and not node.hasAttribute("id") ] self.assertEqual(len(instance_nodes), 1) instance_node = instance_nodes[0] # get the first element whose id attribute is equal to our form's id_string form_nodes = [ node for node in instance_node.childNodes if node.nodeType == Node.ELEMENT_NODE and node.getAttribute("id") == xform.id_string ] form_node = form_nodes[0] # find the formhub node that has a uuid child node formhub_nodes = form_node.getElementsByTagName("formhub") self.assertEqual(len(formhub_nodes), 1) uuid_nodes = formhub_nodes[0].getElementsByTagName("uuid") self.assertEqual(len(uuid_nodes), 1) # check for the calculate bind calculate_bind_nodes = [ node for node in model_node.childNodes if node.nodeType == Node.ELEMENT_NODE and node.tagName == "bind" and node.getAttribute("nodeset") == "/%s/formhub/uuid" % file_name ] self.assertEqual(len(calculate_bind_nodes), 1) calculate_bind_node = calculate_bind_nodes[0] self.assertEqual(calculate_bind_node.getAttribute("calculate"), "'%s'" % xform.uuid)
def test_uuid_injection_in_cascading_select(self): """Test that the uuid is injected in the right instance node for forms with a cascading select""" pre_count = XForm.objects.count() xls_path = os.path.join(self.this_directory, "fixtures", "cascading_selects", "new_cascading_select.xls") file_name, file_ext = os.path.splitext(os.path.split(xls_path)[1]) self.response = MainTestCase._publish_xls_file(self, xls_path) post_count = XForm.objects.count() self.assertEqual(post_count, pre_count + 1) xform = XForm.objects.latest("date_created") # check that the uuid is within the main instance/ the one without an id attribute xml = clean_and_parse_xml(xform.xml) # check for instance nodes that are direct children of the model node model_node = xml.getElementsByTagName("model")[0] instance_nodes = [ node for node in model_node.childNodes if node.nodeType == Node.ELEMENT_NODE and node.tagName.lower() == "instance" and not node.hasAttribute("id") ] self.assertEqual(len(instance_nodes), 1) instance_node = instance_nodes[0] # get the first element whose id attribute is equal to our form's id_string form_nodes = [ node for node in instance_node.childNodes if node.nodeType == Node.ELEMENT_NODE and node.getAttribute("id") == xform.id_string ] form_node = form_nodes[0] # find the formhub node that has a uuid child node formhub_nodes = form_node.getElementsByTagName("formhub") self.assertEqual(len(formhub_nodes), 1) uuid_nodes = formhub_nodes[0].getElementsByTagName("uuid") self.assertEqual(len(uuid_nodes), 1) # check for the calculate bind calculate_bind_nodes = [ node for node in model_node.childNodes if node.nodeType == Node.ELEMENT_NODE and node.tagName == "bind" and node.getAttribute("nodeset") == "/%s/formhub/uuid" % file_name ] self.assertEqual(len(calculate_bind_nodes), 1) calculate_bind_node = calculate_bind_nodes[0] self.assertEqual(calculate_bind_node.getAttribute("calculate"), "'%s'" % xform.uuid)
def get_id_string_from_xml_str(xml_str): xml_obj = clean_and_parse_xml(xml_str) root_node = xml_obj.documentElement return root_node.getAttribute(u"id")
def _set_uuid_in_xml(self, file_name=None): """ Add bind to automatically set UUID node in XML. """ if not file_name: file_name = self.file_name() file_name, file_ext = os.path.splitext(file_name) doc = clean_and_parse_xml(self.xml) model_nodes = doc.getElementsByTagName("model") if len(model_nodes) != 1: raise Exception(u"xml contains multiple model nodes") model_node = model_nodes[0] instance_nodes = [ node for node in model_node.childNodes if node.nodeType == Node.ELEMENT_NODE and node.tagName.lower() == "instance" and not node.hasAttribute("id") ] if len(instance_nodes) != 1: raise Exception(u"Multiple instance nodes without the id " u"attribute, can't tell which is the main one") instance_node = instance_nodes[0] # get the first child whose id attribute matches our id_string survey_nodes = [ node for node in instance_node.childNodes if node.nodeType == Node.ELEMENT_NODE and node.tagName == file_name ] if len(survey_nodes) != 1: raise Exception(u"Multiple survey nodes with the id '%s'" % self.id_string) survey_node = survey_nodes[0] formhub_nodes = [ n for n in survey_node.childNodes if n.nodeType == Node.ELEMENT_NODE and n.tagName == "formhub" ] if len(formhub_nodes) > 1: raise Exception(u"Multiple formhub nodes within main instance node") elif len(formhub_nodes) == 1: formhub_node = formhub_nodes[0] else: formhub_node = survey_node.insertBefore(doc.createElement("formhub"), survey_node.firstChild) uuid_nodes = [ node for node in formhub_node.childNodes if node.nodeType == Node.ELEMENT_NODE and node.tagName == "uuid" ] if len(uuid_nodes) == 0: formhub_node.appendChild(doc.createElement("uuid")) if len(formhub_nodes) == 0: # append the calculate bind node calculate_node = doc.createElement("bind") calculate_node.setAttribute("nodeset", "/%s/formhub/uuid" % file_name) calculate_node.setAttribute("type", "string") calculate_node.setAttribute("calculate", "'%s'" % self.uuid) model_node.appendChild(calculate_node) self.xml = doc.toprettyxml(indent=" ", encoding="utf-8") # hack # http://ronrothman.com/public/leftbraned/xml-dom-minidom-toprettyxml-and-silly-whitespace/ text_re = re.compile(">\n\s+([^<>\s].*?)\n\s+</", re.DOTALL) output_re = re.compile("\n.*(<output.*>)\n( )*") prettyXml = text_re.sub(">\g<1></", self.xml) inlineOutput = output_re.sub("\g<1>", prettyXml) inlineOutput = re.compile("<label>\s*\n*\s*\n*\s*</label>").sub("<label></label>", inlineOutput) self.xml = inlineOutput
def _set_uuid_in_xml(self, file_name=None): """ Add bind to automatically set UUID node in XML. """ if not file_name: file_name = self.file_name() file_name, file_ext = os.path.splitext(file_name) doc = clean_and_parse_xml(self.xml) model_nodes = doc.getElementsByTagName("model") if len(model_nodes) != 1: raise Exception(u"xml contains multiple model nodes") model_node = model_nodes[0] instance_nodes = [ node for node in model_node.childNodes if node.nodeType == Node.ELEMENT_NODE and node.tagName.lower() == "instance" and not node.hasAttribute("id") ] if len(instance_nodes) != 1: raise Exception(u"Multiple instance nodes without the id " u"attribute, can't tell which is the main one") instance_node = instance_nodes[0] # get the first child whose id attribute matches our id_string survey_nodes = [ node for node in instance_node.childNodes if node.nodeType == Node.ELEMENT_NODE and node.tagName == file_name ] if len(survey_nodes) != 1: raise Exception(u"Multiple survey nodes with the id '%s'" % self.id_string) survey_node = survey_nodes[0] formhub_nodes = [ n for n in survey_node.childNodes if n.nodeType == Node.ELEMENT_NODE and n.tagName == "formhub" ] if len(formhub_nodes) > 1: raise Exception( u"Multiple formhub nodes within main instance node") elif len(formhub_nodes) == 1: formhub_node = formhub_nodes[0] else: formhub_node = survey_node.insertBefore( doc.createElement("formhub"), survey_node.firstChild) uuid_nodes = [ node for node in formhub_node.childNodes if node.nodeType == Node.ELEMENT_NODE and node.tagName == "uuid" ] if len(uuid_nodes) == 0: formhub_node.appendChild(doc.createElement("uuid")) if len(formhub_nodes) == 0: # append the calculate bind node calculate_node = doc.createElement("bind") calculate_node.setAttribute("nodeset", "/%s/formhub/uuid" % file_name) calculate_node.setAttribute("type", "string") calculate_node.setAttribute("calculate", "'%s'" % self.uuid) model_node.appendChild(calculate_node) self.xml = doc.toprettyxml(indent=" ", encoding='utf-8') # hack # http://ronrothman.com/public/leftbraned/xml-dom-minidom-toprettyxml-and-silly-whitespace/ text_re = re.compile('>\n\s+([^<>\s].*?)\n\s+</', re.DOTALL) output_re = re.compile('\n.*(<output.*>)\n( )*') prettyXml = text_re.sub('>\g<1></', self.xml) inlineOutput = output_re.sub('\g<1>', prettyXml) inlineOutput = re.compile('<label>\s*\n*\s*\n*\s*</label>').sub( '<label></label>', inlineOutput) self.xml = inlineOutput