def get_xsd_element_occurrences(xsd_string, xpath): """Get the min and max occurrences of the element. Args: xsd_string: xpath: Returns: """ # build the xsd tree xsd_tree = XSDTree.build_tree(xsd_string) # get the namespaces namespaces = get_namespaces(xsd_string) # get the default prefix default_prefix = get_default_prefix(namespaces) # set the element namespace xpath = xpath.replace(default_prefix + ":", LXML_SCHEMA_NAMESPACE) # add the element to the sequence element = xsd_tree.find(xpath) if "minOccurs" in element.attrib: min_occurs = element.attrib["minOccurs"] else: min_occurs = "1" if "maxOccurs" in element.attrib: max_occurs = element.attrib["maxOccurs"] else: max_occurs = "1" return min_occurs, max_occurs
def get_element_by_xpath(xsd_tree, xpath, namespaces=None): """Returns an element from its xpath Args: xsd_tree: xpath: namespaces: Returns: """ if namespaces is not None: # Get default prefix default_prefix = get_default_prefix(namespaces) # Transform xpath into LXML format xpath = xpath.replace(default_prefix + ":", xml_utils_constants.LXML_SCHEMA_NAMESPACE) try: element = xsd_tree.find(xpath) except: raise XMLError('Unable to find an element for the given Xpath.') if element is not None: return element else: raise XMLError('Unable to find an element for the given Xpath.')
def test_get_xsd_prefix(self): xsd_string = ( "<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'></xsd:schema>" ) namespaces = get_namespaces(xsd_string) prefix = get_default_prefix(namespaces) self.assertTrue(prefix == "xsd")
def rename_xsd_element(xsd_string, xpath, new_name): """Rename xsd element. Args: xsd_string: xpath: new_name: Returns: """ # build the xsd tree xsd_tree = XSDTree.build_tree(xsd_string) # get the namespaces namespaces = get_namespaces(xsd_string) # get the default prefix default_prefix = get_default_prefix(namespaces) # set the element namespace xpath = xpath.replace(default_prefix + ":", LXML_SCHEMA_NAMESPACE) # rename element xsd_tree.find(xpath).attrib["name"] = new_name # rebuild xsd string xsd_string = XSDTree.tostring(xsd_tree) # return xsd string return xsd_string
def insert_element_built_in_type(xsd_string, xpath, element_type_name): """Insert element with a builtin type in xsd string. Args: xsd_string: xsd string xpath: xpath where to insert the element element_type_name: name of the type to insert Returns: """ # build the dom tree of the schema being built xsd_tree = XSDTree.build_tree(xsd_string) # get namespaces information for the schema namespaces = get_namespaces(xsd_string) # get the default namespace default_prefix = get_default_prefix(namespaces) # build xpath to element xpath = xpath.replace(default_prefix + ":", LXML_SCHEMA_NAMESPACE) type_name = default_prefix + ':' + element_type_name xsd_tree.find(xpath).append( XSDTree.create_element("{}element".format(LXML_SCHEMA_NAMESPACE), attrib={ 'type': type_name, 'name': element_type_name })) # validate XML schema error = validate_xml_schema(xsd_tree) # if errors, raise exception if error is not None: raise XMLError(error) return XSDTree.tostring(xsd_tree)
def set_xsd_element_occurrences(xsd_string, xpath, min_occurs, max_occurs): """Set occurrences of element. Args: xsd_string: xpath: min_occurs: max_occurs: Returns: """ # build xsd tree xsd_tree = XSDTree.build_tree(xsd_string) # get namespaces namespaces = get_namespaces(xsd_string) # get default prefix default_prefix = get_default_prefix(namespaces) # set the element namespace xpath = xpath.replace(default_prefix + ":", LXML_SCHEMA_NAMESPACE) # add the element to the sequence element = xsd_tree.find(xpath) element.attrib["minOccurs"] = min_occurs element.attrib["maxOccurs"] = max_occurs # save the tree in the session xsd_string = XSDTree.tostring(xsd_tree) # return xsd string return xsd_string
def delete_xsd_element(xsd_string, xpath): """Delete element from tree. Args: xsd_string: xpath: Returns: """ # build xsd tree xsd_tree = XSDTree.build_tree(xsd_string) # get xsd namespaces namespaces = get_namespaces(xsd_string) # get default prefix default_prefix = get_default_prefix(namespaces) # set the element namespace xpath = xpath.replace(default_prefix + ":", LXML_SCHEMA_NAMESPACE) # get element to remove from tree element_to_remove = xsd_tree.find(xpath) # remove element from tree element_to_remove.getparent().remove(element_to_remove) # rebuild xsd string xsd_string = XSDTree.tostring(xsd_tree) # return xsd string return xsd_string
def check_query_form(form_values, template_id, request=None): """Checks that values entered by the user match each element type Args: form_values: template_id: request: Returns: """ template = template_api.get(template_id, request=request) namespaces = get_namespaces(template.content) default_prefix = get_default_prefix(namespaces) # check if there are no errors in the query errors = [] if len(form_values) == 0: errors.append("The query is empty.") for field in form_values: element_value = get_element_value(field) element_name = field.get("name", "Unnamed field") element_type = field.get("type", None) # If there is a type to check if element_type: error = validate_element_value( element_name, element_type, element_value, default_prefix ) if error is not None: errors.append(error) return errors
def _fields_to_query(form_values, template_id, get_dot_notation_to_element_func, use_wildcard): """Takes values from the html tree and creates a query from them Args: form_values: template_id: use_wildcard: get_dot_notation_to_element_func: Returns: """ # get template template = template_api.get(template_id) # get namespaces namespaces = get_namespaces(template.content) # get default prefix default_prefix = get_default_prefix(namespaces) query = dict() for field in form_values: bool_comp = field['operator'] is_not = bool_comp == 'NOT' element_type = field.get('type', None) # get element value value = get_element_value(field) # get comparison operator comparison = get_element_comparison(field) element_id = field['id'] if element_type == "query": try: saved_query = saved_query_api.get_by_id(element_id) except DoesNotExist: raise MongoQueryException( "The saved query does not exist anymore.") criteria = build_query_criteria(json.loads(saved_query.query), is_not) else: data_structure_element = data_structure_element_api.get_by_id( element_id) element = get_dot_notation_to_element_func(data_structure_element, namespaces) criteria = build_criteria(element, comparison, value, element_type, default_prefix, is_not, use_wildcard) if bool_comp == 'OR': query = build_or_criteria(query, criteria) elif bool_comp == 'AND': query = build_and_criteria(query, criteria) else: if form_values.index(field) == 0: query.update(criteria) else: query = build_and_criteria(query, criteria) return query
def update_user_input(request): """Updates the user input of the query builder according to the type of the selected element Args: request: Returns: """ from_element_id = request.POST['elementID'] template_id = request.POST['templateID'] # get schema element data_structure_element = data_structure_element_api.get_by_id( from_element_id) # get template template = template_api.get(template_id) # convert xml path to mongo dot notation namespaces = get_namespaces(template.content) default_prefix = get_default_prefix(namespaces) element_type = data_structure_element.options['type'] user_inputs = get_user_inputs(element_type, data_structure_element, default_prefix) response_dict = {'userInputs': user_inputs, 'element_type': element_type} return HttpResponse(json.dumps(response_dict), content_type='application/javascript')
def insert_sub_elements_query(request): """Inserts a query for a sub element in the query builder Args: request: Returns: """ form_values = json.loads(request.POST["formValues"]) template_id = request.POST["templateID"] criteria_id = request.POST["criteriaID"] # get template template = template_api.get(template_id, request=request) # get template namespaces namespaces = get_namespaces(template.content) # get default prefix default_prefix = get_default_prefix(namespaces) # keep only selected fields form_values = [field for field in form_values if field["selected"] is True] errors = check_query_form(form_values, template_id, request=request) if len(errors) == 0: query = sub_elements_to_query(form_values, namespaces, default_prefix, request) displayed_query = sub_elements_to_pretty_query(form_values, namespaces, request) ui_id = "ui" + criteria_id[4:] temporary_query = SavedQuery( user_id=ExploreExampleAppConfig.name, template=template, query=json.dumps(query), displayed_query=displayed_query, ) saved_query_api.upsert(temporary_query) response_dict = { "criteriaID": criteria_id, "prettyQuery": displayed_query, "uiID": ui_id, "queryID": str(temporary_query.id), } else: return HttpResponseBadRequest("<br/>".join(errors), content_type="application/javascript") return HttpResponse(json.dumps(response_dict), content_type="application/javascript")
def get_sub_elements_query_builder(request): """Build the form for queries on sub elements Args: request: Returns: """ leaves_id = request.POST["leavesID"] template_id = request.POST["templateID"] # get list of ids from string list_leaves_id = leaves_id.split(" ") # get template template = template_api.get(template_id, request=request) # get template namespaces namespaces = get_namespaces(template.content) # get default prefix default_prefix = get_default_prefix(namespaces) # get the parent name using the first schema element of the list parent_name = get_parent_name(list_leaves_id[0], namespaces, request) form_fields = [] for leaf_id in list_leaves_id: data_structure_element = data_structure_element_api.get_by_id( leaf_id, request) element_type = data_structure_element.options["type"] element_name = data_structure_element.options["name"] user_inputs = get_user_inputs(element_type, data_structure_element, default_prefix) form_fields.append({ "element_id": leaf_id, "element_name": element_name, "element_type": element_type, "html": user_inputs, }) response_dict = { "subElementQueryBuilder": render_sub_elements_query(parent_name, form_fields) } return HttpResponse(json.dumps(response_dict), content_type="application/javascript")
def change_xsd_element_type(xsd_string, xpath, type_name): """Change the type of an element (e.g. sequence -> choice). Args: xsd_string: xpath: type_name: Returns: """ xsd_tree = XSDTree.build_tree(xsd_string) namespaces = get_namespaces(xsd_string) default_prefix = get_default_prefix(namespaces) # set the element namespace xpath = xpath.replace(default_prefix + ":", LXML_SCHEMA_NAMESPACE) xsd_tree.find(xpath).tag = LXML_SCHEMA_NAMESPACE + type_name # rebuild xsd string xsd_string = XSDTree.tostring(xsd_tree) # return xsd string return xsd_string
def test_get_no_prefix(self): xsd_string = "<schema></schema>" namespaces = get_namespaces(xsd_string) prefix = get_default_prefix(namespaces) self.assertTrue(prefix == "")
def _insert_element_type(xsd_string, xpath, type_content, element_type_name, include_url): """Insert an element of given type in xsd string. Args: xsd_string: xsd string xpath: xpath where to insert the element type_content: string content of the type to insert element_type_name: name of the type include_url: url used to reference the type in schemaLocation Returns: """ # build the dom tree of the schema being built xsd_tree = XSDTree.build_tree(xsd_string) # get namespaces information for the schema namespaces = get_namespaces(xsd_string) # get the default namespace default_prefix = get_default_prefix(namespaces) # get target namespace information target_namespace, target_namespace_prefix = get_target_namespace( xsd_tree, namespaces) # build xpath to element xpath = xpath.replace(default_prefix + ":", LXML_SCHEMA_NAMESPACE) # build xsd tree type_xsd_tree = XSDTree.build_tree(type_content) # get namespaces information for the type type_namespaces = get_namespaces(type_content) # get target namespace information type_target_namespace, type_target_namespace_prefix = get_target_namespace( type_xsd_tree, type_namespaces) # get the type from the included/imported file # If there is a complex type element_type = type_xsd_tree.find( "{}complexType".format(LXML_SCHEMA_NAMESPACE)) if element_type is None: # If there is a simple type element_type = type_xsd_tree.find( "{}simpleType".format(LXML_SCHEMA_NAMESPACE)) type_name = element_type.attrib["name"] # format type name to avoid forbidden xml characters element_type_name = _get_valid_xml_name(element_type_name) # variable that indicates if namespaces map needs to be updated update_ns_map = False # Schema without target namespace if target_namespace is None: # Type without target namespace if type_target_namespace is None: # create type name with namespace ns_type_name = type_name # create include element dependency_tag = "include" dependency_attrib = {"schemaLocation": include_url} # Type with target namespace else: # create type name with namespace ns_type_name = _get_ns_type_name(type_target_namespace_prefix, type_name, prefix_required=True) # create import element dependency_tag = "import" dependency_attrib = { "schemaLocation": include_url, "namespace": type_target_namespace, } update_ns_map = True # Schema with target namespace else: # Type without target namespace if type_target_namespace is None: # create type name with namespace ns_type_name = _get_ns_type_name(target_namespace_prefix, type_name) # create include element dependency_tag = "include" dependency_attrib = {"schemaLocation": include_url} # Type with target namespace else: # Same target namespace as base template if target_namespace == type_target_namespace: # create type name with namespace ns_type_name = _get_ns_type_name(target_namespace_prefix, type_name) # create include element dependency_tag = "include" dependency_attrib = {"schemaLocation": include_url} # Different target namespace as base template else: # create type name with namespace ns_type_name = _get_ns_type_name(type_target_namespace_prefix, type_name, prefix_required=True) # create import element dependency_tag = "import" dependency_attrib = { "schemaLocation": include_url, "namespace": type_target_namespace, } update_ns_map = True # create dependency element dependency_element = _create_xsd_element(dependency_tag, dependency_attrib) # create xsd element xsd_element = _create_xsd_element("element", attrib={ "name": element_type_name, "type": ns_type_name }) # check if dependency element (include/import) is already present dependency_tag = "{0}[@schemaLocation='{1}']".format( dependency_element.tag, dependency_element.attrib["schemaLocation"]) dependency_present = xsd_tree.find(dependency_tag) is not None if not dependency_present: # add dependency element (include/import) xsd_tree.getroot().insert(0, dependency_element) # add xsd element xsd_tree.find(xpath).append(xsd_element) # if namespace map of the schema needs to be updated if not dependency_present and update_ns_map: root = xsd_tree.getroot() root_ns_map = root.nsmap if (type_target_namespace_prefix in list(root_ns_map.keys()) and root_ns_map[type_target_namespace_prefix] != type_target_namespace): raise CoreError( "The namespace prefix is already declared for a different namespace." ) else: root_ns_map[type_target_namespace_prefix] = type_target_namespace new_root = XSDTree.create_element(root.tag, nsmap=root_ns_map, attrib=root.attrib) new_root[:] = root[:] # return result tree return new_root else: # return result tree return xsd_tree