예제 #1
0
 def test_target_namespace_with_prefix_returns_target_namespace_and_prefix(
         self):
     xsd_string = "<schema targetNamespace='namespace' xmlns:ns='namespace'></schema>"
     xsd_tree = XSDTree.build_tree(xsd_string)
     namespaces = get_namespaces(xsd_string)
     self.assertEquals(('namespace', 'ns'),
                       get_target_namespace(xsd_tree, namespaces))
예제 #2
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)
예제 #3
0
def _update_attribute(xsd_string, xpath, attribute, value=None):
    """Updates an attribute (sets the value or deletes)

    Args:
        xsd_string:
        xpath: xpath of the element to update
        attribute: name of the attribute to update
        value: value of the attribute to set

    Returns:

    """
    # Build the XSD tree
    xsd_tree = XSDTree.build_tree(xsd_string)
    # Get namespaces
    namespaces = get_namespaces(xsd_string)
    # Get XSD element using its xpath
    element = get_element_by_xpath(xsd_tree, xpath, namespaces)

    # Add or update the attribute
    if value is not None:
        # Set element attribute with value
        element.attrib[attribute] = value
    else:
        # Deletes attribute
        if attribute in element.attrib:
            del element.attrib[attribute]

    # Converts XSD tree back to string
    updated_xsd_string = XSDTree.tostring(xsd_tree)

    return updated_xsd_string
예제 #4
0
def _update_appinfo_element(xsd_string, xpath, appinfo_name, value=None):
    """Updates an appinfo element

    Args:
        xsd_string:
        xpath: xpath to element to update
        appinfo_name: name of the attribute to update
        value: value to set

    Returns:

    """
    # Build the XSD tree
    xsd_tree = XSDTree.build_tree(xsd_string)
    # Get namespaces
    namespaces = get_namespaces(xsd_string)
    # Get XSD element using its xpath
    element = get_element_by_xpath(xsd_tree, xpath, namespaces)

    if value is not None:
        # If a value is provided, create or update the appinfo
        add_appinfo_child_to_element(element, appinfo_name, value)
    else:
        # value is None, deletes the appinfo if present
        delete_appinfo_child_from_element(element, appinfo_name)

    # Converts XSD tree back to string
    updated_xsd_string = XSDTree.tostring(xsd_tree)

    return updated_xsd_string
예제 #5
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
예제 #6
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")
예제 #7
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
예제 #8
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
예제 #9
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
예제 #10
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
예제 #12
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')
예제 #13
0
 def test_get_element_xpath_matching_element_with_xs_namespace_prefix(self):
     xsd_string = "<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'><xs:element><xs:complexType>" \
                  "</xs:complexType></xs:element></xs:schema>"
     xpath = "xs:element/xs:complexType"
     xsd_tree = XSDTree.build_tree(xsd_string)
     namespaces = get_namespaces(xsd_string)
     element = get_element_by_xpath(xsd_tree, xpath, namespaces)
     self.assertTrue(element is not None)
예제 #14
0
 def test_get_element_xpath_not_matching_element_without_namespace_prefix(
         self):
     xsd_string = "<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'><xsd:element><xsd:complexType>" \
                  "</xsd:complexType></xsd:element></xsd:schema>"
     xpath = "element/complexType"
     xsd_tree = XSDTree.build_tree(xsd_string)
     namespaces = get_namespaces(xsd_string)
     with self.assertRaises(XMLError):
         get_element_by_xpath(xsd_tree, xpath, namespaces)
예제 #15
0
 def test_get_namespaces_two_namespaces(self):
     xsd_string = """
         <xs:schema
             xmlns:xs="http://www.w3.org/2001/XMLSchema" 
             xmlns:test="test">
         </xs:schema>
     """
     namespaces = get_namespaces(xsd_string)
     self.assertTrue("xs" in list(namespaces.keys())
                     and "test" in list(namespaces.keys()))
예제 #16
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")
예제 #17
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")
예제 #18
0
def _get_target_namespace_prefix(ref_xml_schema_content, xml_doc_tree):
    """ Get the target namespace prefix.

    Args:
        ref_xml_schema_content:
        xml_doc_tree:

    Returns:

    """
    namespaces = get_namespaces(ref_xml_schema_content)
    target_namespace, target_ns_prefix = get_target_namespace(
        xml_doc_tree, namespaces)

    return target_ns_prefix
예제 #19
0
def has_xsl_namespace(xml_string):
    """True if XML has the XSL namespace.

    Args:
        xml_string:

    Returns:

    """
    has_namespace = False
    try:
        has_namespace = XSL_NAMESPACE in list(get_namespaces(xml_string).values())
    except Exception as e:
        logger.warning("has_xsl_namespace threw an exception: ".format(str(e)))

    return has_namespace
예제 #20
0
def has_xsl_namespace(xml_string):
    """True if XML has the XSL namespace.

    Args:
        xml_string:

    Returns:

    """
    has_namespace = False
    try:
        has_namespace = XSL_NAMESPACE in get_namespaces(xml_string).values()
    except Exception:
        pass

    return has_namespace
예제 #21
0
def get_xpath_with_target_namespace(xpath, xsd_string):
    """Adds target namespace to a given XPath

    Params:
        xpath:
        xsd_string:

    Returns:

    """
    namespaces = get_target_namespace(XSDTree.build_tree(xsd_string),
                                      get_namespaces(xsd_string))

    xpath = xpath.format(namespaces[1])

    if namespaces[1] == "":
        xpath = xpath.replace(":", "")
        namespaces = None
    else:
        namespaces = {namespaces[1]: namespaces[0]}

    return xpath, namespaces
예제 #22
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
예제 #23
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
예제 #24
0
 def test_target_namespace_no_prefix_returns_target_namespace_only(self):
     xsd_string = "<schema targetNamespace='namespace'></schema>"
     xsd_tree = XSDTree.build_tree(xsd_string)
     namespaces = get_namespaces(xsd_string)
     self.assertEqual(("namespace", ""),
                      get_target_namespace(xsd_tree, namespaces))
예제 #25
0
 def test_no_target_namespace_returns_none_values(self):
     xsd_string = "<schema></schema>"
     xsd_tree = XSDTree.build_tree(xsd_string)
     namespaces = get_namespaces(xsd_string)
     self.assertEqual((None, ""),
                      get_target_namespace(xsd_tree, namespaces))
예제 #26
0
 def test_get_no_prefix(self):
     xsd_string = "<schema></schema>"
     namespaces = get_namespaces(xsd_string)
     prefix = get_default_prefix(namespaces)
     self.assertTrue(prefix == "")
예제 #27
0
 def test_get_namespaces_xml_namespace(self):
     xsd_string = (
         "<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'></xs:schema>"
     )
     namespaces = get_namespaces(xsd_string)
     self.assertTrue("xml" in list(namespaces.keys()))
예제 #28
0
 def test_get_namespaces_invalid_file(self):
     xsd_string = "invalid"
     with self.assertRaises(etree.XMLSyntaxError):
         get_namespaces(xsd_string)
예제 #29
0
 def test_get_namespaces_one_namespace_prefix_is_key(self):
     xsd_string = """
         <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'></xs:schema>
     """
     namespaces = get_namespaces(xsd_string)
     self.assertTrue("xs" in list(namespaces.keys()))
예제 #30
0
 def test_get_namespaces_one_namespace_namespace_is_value(self):
     xsd_string = (
         "<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'></xs:schema>"
     )
     namespaces = get_namespaces(xsd_string)
     self.assertTrue(namespaces["xs"] == "http://www.w3.org/2001/XMLSchema")