Пример #1
0
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
Пример #2
0
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.')
Пример #3
0
 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")
Пример #4
0
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
Пример #5
0
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)
Пример #6
0
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
Пример #7
0
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
Пример #8
0
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
Пример #10
0
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')
Пример #11
0
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")
Пример #12
0
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")
Пример #13
0
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
Пример #14
0
 def test_get_no_prefix(self):
     xsd_string = "<schema></schema>"
     namespaces = get_namespaces(xsd_string)
     prefix = get_default_prefix(namespaces)
     self.assertTrue(prefix == "")
Пример #15
0
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