Beispiel #1
0
    def visit_import(self, node, parent):
        """
            <import
              id = ID
              namespace = anyURI
              schemaLocation = anyURI
              {any attributes with non-schema Namespace}...>
            Content: (annotation?)
            </import>
        """
        namespace = node.get('namespace')
        location = node.get('schemaLocation')
        schema_node = None

        # Check if a schemaLocation is defined, if it isn't perhaps the
        # namespaces references to an internal xml schema. Otherwise we just
        # raise an error for now.
        if not location:
            if namespace:
                location = namespace
                try:
                    schema_node = self.parser_context.schema_nodes.get(namespace)
                except KeyError:
                    raise ValueError("No schema for namespace=%s" % namespace)

            if not schema_node:
                raise ValueError("schemaLocation is required")

        # If a schemaLocation is defined then make the location absolute based
        # on the base url and see if the schema is already processed (for
        # cyclic schema references). Otherwise load the data.
        else:
            location = absolute_location(location, self.schema._base_url)
            schema = self.parser_context.schema_objects.get(location)
            if schema:
                logger.debug("Returning existing schema: %r", location)
                self.schema._imports[namespace] = schema
                return schema

            schema_node = load_external(
                location, self.schema._transport, self.parser_context)

        # If this schema location is 'internal' then retrieve the original
        # location since that is used as base url for sub include/imports
        if location in self.parser_context.schema_locations:
            base_url = self.parser_context.schema_locations[location]
        else:
            base_url = location

        schema = self.schema.__class__(
            schema_node, self.schema._transport, location,
            self.parser_context, base_url)

        self.schema._imports[namespace] = schema
        return schema
Beispiel #2
0
    def visit_include(self, node, parent):
        """
        <include
          id = ID
          schemaLocation = anyURI
          {any attributes with non-schema Namespace}...>
        Content: (annotation?)
        </include>
        """
        if not node.get('schemaLocation'):
            raise NotImplementedError("schemaLocation is required")
        location = node.get('schemaLocation')

        schema_node = load_external(
            location, self.schema._transport, self.parser_context,
            base_url=self.schema._base_url)
        return self.visit_schema(schema_node)
Beispiel #3
0
    def visit_include(self, node, parent):
        """
        <include
          id = ID
          schemaLocation = anyURI
          {any attributes with non-schema Namespace}...>
        Content: (annotation?)
        </include>
        """
        if not node.get('schemaLocation'):
            raise NotImplementedError("schemaLocation is required")
        location = node.get('schemaLocation')

        if location in self._includes:
            return

        schema_node = load_external(
            location, self.schema._transport, base_url=self.document._base_url)
        self._includes.add(location)

        return self.visit_schema(schema_node)
Beispiel #4
0
    def visit_import(self, node, parent):
        """
            <import
              id = ID
              namespace = anyURI
              schemaLocation = anyURI
              {any attributes with non-schema Namespace}...>
            Content: (annotation?)
            </import>
        """
        schema_node = None
        namespace = node.get('namespace')
        location = node.get('schemaLocation')
        if location:
            location = absolute_location(location, self.document._base_url)

        if not namespace and not self.document._target_namespace:
            raise XMLParseError(
                "The attribute 'namespace' must be existent if the "
                "importing schema has no target namespace.")

        # Check if the schema is already imported before based on the
        # namespace. Schema's without namespace are registered as 'None'
        schema = self.parser_context.schema_objects.get(namespace)
        if schema:
            if location and schema._location != location:
                # Use same warning message as libxml2
                message = (
                    "Skipping import of schema located at %r " +
                    "for the namespace %r, since the namespace was " +
                    "already imported with the schema located at %r"
                    ) % (location, namespace or '(null)', schema._location)
                warnings.warn(message, ZeepWarning, stacklevel=6)

                return
            logger.debug("Returning existing schema: %r", location)
            self.document._imports[namespace] = schema
            return schema

        # Hardcode the mapping between the xml namespace and the xsd for now.
        # This seems to fix issues with exchange wsdl's, see #220
        if not location and namespace == 'http://www.w3.org/XML/1998/namespace':
            location = 'https://www.w3.org/2001/xml.xsd'

        # Silently ignore import statements which we can't resolve via the
        # namespace and doesn't have a schemaLocation attribute.
        if not location:
            logger.debug(
                "Ignoring import statement for namespace %r " +
                "(missing schemaLocation)", namespace)
            return

        # Load the XML
        schema_node = load_external(
            location, self.document._transport, self.parser_context)

        # Check if the xsd:import namespace matches the targetNamespace. If
        # the xsd:import statement didn't specify a namespace then make sure
        # that the targetNamespace wasn't declared by another schema yet.
        schema_tns = schema_node.get('targetNamespace')
        if namespace and schema_tns and namespace != schema_tns:
            raise XMLParseError((
                "The namespace defined on the xsd:import doesn't match the "
                "imported targetNamespace located at %r "
                ) % (location))
        elif schema_tns in self.parser_context.schema_objects:
            schema = self.parser_context.schema_objects.get(schema_tns)
            message = (
                "Skipping import of schema located at %r " +
                "for the namespace %r, since the namespace was " +
                "already imported with the schema located at %r"
                ) % (location, namespace or '(null)', schema._location)
            warnings.warn(message, ZeepWarning, stacklevel=6)

        # If this schema location is 'internal' then retrieve the original
        # location since that is used as base url for sub include/imports
        if location in self.parser_context.schema_locations:
            base_url = self.parser_context.schema_locations[location]
        else:
            base_url = location

        schema = self.document.__class__(
            schema_node, self.document._transport, self.schema, location,
            self.parser_context, base_url)

        self.document._imports[namespace] = schema
        return schema
Beispiel #5
0
    def visit_import(self, node, parent):
        """
            <import
              id = ID
              namespace = anyURI
              schemaLocation = anyURI
              {any attributes with non-schema Namespace}...>
            Content: (annotation?)
            </import>
        """
        schema_node = None
        namespace = node.get('namespace')
        location = node.get('schemaLocation')
        if location:
            location = absolute_location(location, self.schema._base_url)

        if not namespace and not self.schema._target_namespace:
            raise XMLParseError(
                "The attribute 'namespace' must be existent if the "
                "importing schema has no target namespace.")

        # Check if the schema is already imported before based on the
        # namespace. Schema's without namespace are registered as 'None'
        schema = self.parser_context.schema_objects.get(namespace)
        if schema:
            if location and schema._location != location:
                # Use same warning message as libxml2
                message = ("Skipping import of schema located at %r " +
                           "for the namespace %r, since the namespace was " +
                           "already imported with the schema located at %r"
                           ) % (location, namespace
                                or '(null)', schema._location)
                warnings.warn(message, ZeepWarning, stacklevel=6)

                return
            logger.debug("Returning existing schema: %r", location)
            self.schema._imports[namespace] = schema
            return schema

        # Silently ignore import statements which we can't resolve via the
        # namespace and doesn't have a schemaLocation attribute.
        if not location:
            logger.debug(
                "Ignoring import statement for namespace %r " +
                "(missing schemaLocation)", namespace)
            return

        # Load the XML
        schema_node = load_external(location, self.schema._transport,
                                    self.parser_context)

        # Check if the xsd:import namespace matches the targetNamespace. If
        # the xsd:import statement didn't specify a namespace then make sure
        # that the targetNamespace wasn't declared by another schema yet.
        schema_tns = schema_node.get('targetNamespace')
        if namespace and schema_tns and namespace != schema_tns:
            raise XMLParseError(
                ("The namespace defined on the xsd:import doesn't match the "
                 "imported targetNamespace located at %r ") % (location))
        elif schema_tns in self.parser_context.schema_objects:
            schema = self.parser_context.schema_objects.get(schema_tns)
            message = ("Skipping import of schema located at %r " +
                       "for the namespace %r, since the namespace was " +
                       "already imported with the schema located at %r") % (
                           location, namespace or '(null)', schema._location)
            warnings.warn(message, ZeepWarning, stacklevel=6)

        # If this schema location is 'internal' then retrieve the original
        # location since that is used as base url for sub include/imports
        if location in self.parser_context.schema_locations:
            base_url = self.parser_context.schema_locations[location]
        else:
            base_url = location

        schema = self.schema.__class__(schema_node, self.schema._transport,
                                       location, self.parser_context, base_url)

        self.schema._imports[namespace] = schema
        return schema
Beispiel #6
0
    def visit_import(self, node, parent):
        """
            <import
              id = ID
              namespace = anyURI
              schemaLocation = anyURI
              {any attributes with non-schema Namespace}...>
            Content: (annotation?)
            </import>
        """
        schema_node = None
        namespace = node.get('namespace')
        location = node.get('schemaLocation')
        if location:
            location = absolute_location(location, self.schema._base_url)

        if not namespace and not self.schema._target_namespace:
            raise XMLParseError(
                "The attribute 'namespace' must be existent if the "
                "importing schema has no target namespace.")

        # Check if the schema is already imported before based on the
        # namespace. Schema's without namespace are registered as 'None'
        schema = self.parser_context.schema_objects.get(namespace)
        if schema:
            if location and schema._location != location:
                # Raise same error message as libxml2
                raise XMLParseError((
                    "Conflicting import of schema located at %r " +
                    "for the namespace %r, since the namespace was " +
                    "already imported with the schema located at %r"
                    ) % (location, namespace or '(null)', schema._location))
                return
            logger.debug("Returning existing schema: %r", location)
            self.schema._imports[namespace] = schema
            return schema

        # Check if if the namespace references an internal schema. Internal
        # schema's are created for multiple xsd:schema definitions in a wsdl
        try:
            schema_node = self.parser_context.schema_nodes.get(namespace)
        except KeyError:
            pass

        # Silently ignore import statements which we can't resolve via the
        # namespace and doesn't have a schemaLocation attribute.
        if not location:
            logger.debug(
                "Ignoring import statement for namespace %r " +
                "(missing schemaLocation)", namespace)
            return

        # Load the XML
        schema_node = load_external(
            location, self.schema._transport, self.parser_context)

        # Check if the xsd:import namespace matches the targetNamespace. If
        # the xsd:import statement didn't specify a namespace then make sure
        # that the targetNamespace wasn't declared by another schema yet.
        schema_tns = schema_node.get('targetNamespace')
        if namespace and schema_tns and namespace != schema_tns:
            raise XMLParseError((
                "The namespace defined on the xsd:import doesn't match the "
                "imported targetNamespace located at %r "
                ) % (location))
        elif schema_tns in self.parser_context.schema_objects:
            schema = self.parser_context.schema_objects.get(schema_tns)
            raise XMLParseError((
                "Conflicting import of schema located at %r " +
                "for the namespace %r, since the namespace was " +
                "already imported with the schema located at %r"
                ) % (location, namespace or '(null)', schema._location))

        # If this schema location is 'internal' then retrieve the original
        # location since that is used as base url for sub include/imports
        if location in self.parser_context.schema_locations:
            base_url = self.parser_context.schema_locations[location]
        else:
            base_url = location

        schema = self.schema.__class__(
            schema_node, self.schema._transport, location,
            self.parser_context, base_url)

        self.schema._imports[namespace] = schema
        return schema
Beispiel #7
0
    def visit_import(self, node, parent):
        """
            <import
              id = ID
              namespace = anyURI
              schemaLocation = anyURI
              {any attributes with non-schema Namespace}...>
            Content: (annotation?)
            </import>
        """
        schema_node = None
        namespace = node.get('namespace')
        location = node.get('schemaLocation')
        if location:
            location = absolute_location(location, self.document._base_url)

        if not namespace and not self.document._target_namespace:
            raise XMLParseError(
                "The attribute 'namespace' must be existent if the "
                "importing schema has no target namespace.")

        # Check if the schema is already imported before based on the
        # namespace. Schema's without namespace are registered as 'None'
        schema = self.schema._get_schema_document(namespace, fail_silently=True)
        if schema:
            if location and schema._location == location:
                logger.debug("Returning existing schema: %r", location)
                self.document.register_import(namespace, schema)
                return schema
            else:
                # Use same warning message as libxml2
                message = (
                    "Skipping import of schema located at %r " +
                    "for the namespace %r, since the namespace was " +
                    "already imported with the schema located at %r"
                    ) % (location, namespace or '(null)', schema._location)
                warnings.warn(message, ZeepWarning, stacklevel=6)
                return

        # Hardcode the mapping between the xml namespace and the xsd for now.
        # This seems to fix issues with exchange wsdl's, see #220
        if not location and namespace == 'http://www.w3.org/XML/1998/namespace':
            location = 'https://www.w3.org/2001/xml.xsd'

        # Silently ignore import statements which we can't resolve via the
        # namespace and doesn't have a schemaLocation attribute.
        if not location:
            logger.debug(
                "Ignoring import statement for namespace %r " +
                "(missing schemaLocation)", namespace)
            return

        # Load the XML
        schema_node = load_external(location, self.schema._transport)

        # Check if the xsd:import namespace matches the targetNamespace. If
        # the xsd:import statement didn't specify a namespace then make sure
        # that the targetNamespace wasn't declared by another schema yet.
        schema_tns = schema_node.get('targetNamespace')
        if namespace and schema_tns and namespace != schema_tns:
            raise XMLParseError((
                "The namespace defined on the xsd:import doesn't match the "
                "imported targetNamespace located at %r "
                ) % (location))
        elif self.schema._has_schema_document(schema_tns):
            schema = self.schema._get_schema_document(schema_tns)
            message = (
                "Skipping import of schema located at %r " +
                "for the namespace %r, since the namespace was " +
                "already imported with the schema located at %r"
                ) % (location, namespace or '(null)', schema._location)
            warnings.warn(message, ZeepWarning, stacklevel=6)

        schema = self.schema.create_new_document(schema_node, location)
        self.document.register_import(namespace, schema)
        return schema