Example #1
0
    def __init__(self, xsd_file):
        self._xsd = None
        self._xml_schema = None

        self.namespaces = self.XML_SCHEMA_NAMESPACES.copy()
        "Namespaces used by XSD file"

        self.target_namespace = None
        "Target namespace URI"

        self.target_prefix = ''
        "Namespace prefix for declarations"

        # Temporary mods for preserve types declaration order for Fortran generation
        from collections import OrderedDict
        self.types = OrderedDict()  # {}
        "Map XSD global types to XSDType instance"

        self.attributes = {}
        "Map XSD global attributes to XSDType instance"

        self.attribute_groups = {}
        "Group XSD attributes definitions"

        self.elements = {}
        "Map XSD global elements to XSDType instance"

        self.groups = {}
        "Group XSD elements definitions"

        try:
            self._xsd = ElementTree.parse(xsd_file)
        except ElementTree.ParseError as e:
            raise FileFormatError('XML', xsd_file, e.msg)
        else:
            self._xsd_file = xsd_file

        try:
            self._xml_schema = ElementTree.XMLSchema(self._xsd)
        except AttributeError:
            logger.info("XSD validation is not available!")
        except ElementTree.XMLSchemaError as e:
            logger.error("XSD schema error: %s " % repr(e))
            raise

        # Set the namespaces information
        schema_elem = self.getroot()
        self.target_namespace = schema_elem.attrib['targetNamespace']
        logger.debug("Target namespace: %s" % self.target_namespace)

        if hasattr(schema_elem, 'nsmap'):
            # lxml loaded
            for prefix, namespace in schema_elem.nsmap.items():
                self.namespaces[prefix
                                or ''] = namespace  # Change None key with ''
        else:
            # xml.etree.ElementTree loaded: need to get namespaces from file
            for event, node in ElementTree.iterparse(self._xsd_file,
                                                     events=['start-ns']):
                self.namespaces[node[0]] = node[1]
        logger.debug('Namespaces: {0}'.format(self.namespaces))

        # Set namespace prefix for schema declarations
        for prefix in self.namespaces:
            if self.namespaces[prefix] == self.target_namespace:
                self.target_prefix = prefix
                if prefix:
                    prefix = '%s:' % prefix
                break
        else:
            prefix = ''
        logger.debug("Use prefix '%s' for schema declarations" % prefix)

        # Build lookup maps using XSD declarations
        logger.debug("### Add global simple types ###")
        add_xsd_types_to_dict(self.findall('./xsd:simpleType'),
                              self.types,
                              xsd_simple_type_factory,
                              xsd_types=self.types,
                              prefix=prefix)

        logger.debug("### Add global attributes ###")
        counter = 0
        for elem in self.findall('./xsd:attributes'):
            self.attributes.update([
                xsd_attribute_type_factory(elem,
                                           xsd_types=self.types,
                                           prefix=prefix)
            ])
            counter += 1
        logger.debug("%d global attributes added" % counter)

        logger.debug("### Add attribute groups ###")
        counter = 0
        for elem in self.findall('./xsd:attributeGroup'):
            try:
                name = elem.attrib['name']
            except KeyError:
                raise XMLSchemaValidationError(
                    "Missing 'name' attribute for {}".format(elem))
            if name in self.attribute_groups:
                raise XMLSchemaValidationError(
                    "Duplicate attributeGroup: {}".format(name))

            self.attribute_groups[name] = OrderedDict([
                xsd_attribute_type_factory(child,
                                           xsd_types=self.types,
                                           prefix=prefix) for child in elem
                if child.tag == _ATTRIBUTE_TAG
            ])
            counter += 1
        logger.debug("%d attribute groups added" % counter)

        logger.debug("### Add global complex types ###")
        add_xsd_types_to_dict(self.findall('./xsd:complexType'),
                              self.types,
                              xsd_complex_type_factory,
                              xsd_types=self.types,
                              prefix=prefix,
                              xsd_attributes=self.attributes)

        logger.debug("### Add content model groups ###")
        counter = 0
        for elem in self.findall('./xsd:group'):
            try:
                name = elem.attrib['name']
            except KeyError:
                raise XMLSchemaValidationError(
                    "Missing 'name' attribute for {}".format(elem))
            if name in self.groups:
                raise XMLSchemaValidationError(
                    "Duplicate group: {}".format(name))

            from .xsdtypes import xsd_group_factory
            self.groups[name] = xsd_group_factory(
                elem,
                xsd_groups=self.groups,
                xsd_types=self.types,
                xsd_attributes=self.attributes,
                xsd_attribute_groups=self.attribute_groups)
            counter += 1
        logger.debug("%d XSD named groups added" % counter)

        logger.debug("### Add elements starting from root element(s) ###")
        for elem in self.findall('./xsd:element'):
            xsd_element_factory(elem,
                                parent_path=None,
                                prefix=prefix,
                                xsd_elements=self.elements,
                                xsd_types=self.types,
                                xsd_attributes=self.attributes,
                                xsd_attribute_groups=self.attribute_groups)
        logger.debug("%d XSD elements added" % len(self.elements))