Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Extension] Provide more generic extension point #135

Closed
blaggacao opened this issue Sep 30, 2019 · 3 comments
Closed

[Extension] Provide more generic extension point #135

blaggacao opened this issue Sep 30, 2019 · 3 comments
Labels
stale PR/Issue without recent activity, it'll be soon closed automatically.

Comments

@blaggacao
Copy link

Quoting: XSD/common/UBL-ExtensionContentDataType-2.1.xsd:18 ff.

  <!--import here all extension schemas-->
  <xsd:import namespace=
     "urn:oasis:names:specification:ubl:schema:xsd:CommonSignatureComponents-2"
              schemaLocation="UBL-CommonSignatureComponents-2.1.xsd"/>

We need a cleaner mechanism (at least for UBL standard documents) to validate the schema structure against UBL "conformant" cutomizations through the UBLExtensions mechanism.

@blaggacao
Copy link
Author

blaggacao commented Sep 30, 2019

It seems, this does the trick:

    @api.model
    def _ubl_check_xml_schema_dian_extensions(self, xml_string, document, version='2.1'):
        """Validate the XML file against the XSD"""

        xsd_file = 'l10n_co_edi/validator/data/xsd-%s/maindoc/DIAN_UBL_Structures.xsd' % (
            version)
        xsd_etree_obj = etree.parse(file_open(xsd_file))
        official_schema = etree.XMLSchema(xsd_etree_obj)

        # Recreate nsmap to generate ElementMaker Syntax (test)
        # Trying out ElementMaker Syntax (test)
        nsmap, ns = self._ubl_get_nsmap_namespace("Dummy", version=version)
        del nsmap[None]  # Dummy Namespace
        try:
            t = etree.parse(BytesIO(xml_string)).find(
                'ext:UBLExtensions/ext:UBLExtension[1]/ext:ExtensionContent/',
                namespaces=nsmap)
            official_schema.assertValid(t)
        except Exception as e:
            # if the validation of the XSD fails, we arrive here
            logger = logging.getLogger(__name__)
            logger.warning(
                "The XML file is invalid against the XML Schema Definition")
            logger.warning(etree.tostring(t))
            logger.warning(e)
            raise UserError(_(
                "The UBL XML file is not valid against the official "
                "XML Schema Definition. The XML file and the "
                "full error have been written in the server logs. "
                "Here is the error, which may give you an idea on the "
                "cause of the problem : %s.")
                % str(e))
        return True

However, it depends on the extension order (a better Xpath with ancestor would do).

Though, I don't think providing validation logic as code is in line with the XMLSchema ideas.

Problem is, injecting an import is not possible as the imports are only resolved as the XML is parsed to a XMLSchema, the initial XML parsing (when we could still manipulate the tree) doesn't load imports, so there is no handle to this file.

Maybe shadowing the file all together?

Or just duplicate the UBL xsl in custom implementations (which kind of respects the lema of completeness of the xsd specification by itself).

Any ideas or thoughts?

@blaggacao
Copy link
Author

Current patch would look like this:

    def _get_uml_extensions(self, document, version='2.1'):
        """ This mehtod is meant to be overriden by localizaiton modules.

        returns a list of tuples

        [(
            ExtensionRootElement,
            ExtensionValidationFileString - fed to `odoo.tools.file_open`
        )]

        Example:
        [(
            'sts:DianExtensions',
            'l10n_co_edi/validator/data/xsd-2.1/maindoc/DIAN_UBL_Structures.xsd'
        )]
        """

        return []

    @api.model
    def _ubl_check_xml_schema_uml_extensions(self, tree, document, version='2.1'):
        """Validate the XML file against the UMLExtension Schemata"""

        for root, xsd_file in self._get_uml_extensions(document, version=version):

            xsd_etree_obj = etree.parse(file_open(xsd_file))
            extension_schema = etree.XMLSchema(xsd_etree_obj)

            # Recreate nsmap for propper prefixing
            nsmap, _ns = self._ubl_get_nsmap_namespace("Dummy", version=version)
            del nsmap[None]  # Dummy Namespace
            t = tree.find(
                "ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/" +
                root,
                namespaces=nsmap,
            )
            try:
                extension_schema.assertValid(t)
            except Exception as e:
                # if the validation of the XSD fails, we arrive here
                logger = logging.getLogger(__name__)
                logger.warning("The UBLExtension is invalid against the XML Schema Definition")
                logger.warning(etree.tostring(t))
                logger.warning(e)
                raise UserError(
                    _(
                        "The UBLExtension is not valid against the official "
                        "XML Schema Definition. The XML file and the "
                        "full error have been written in the server logs. "
                        "Here is the error, which may give you an idea on the "
                        "cause of the problem : %s."
                    )
                    % str(e)
                )
        return True


    @api.model
    def _ubl_check_xml_schema(self, xml_string, document, version='2.1'):
        """Validate the XML file against the XSD"""
        xsd_file = 'base_ubl/data/xsd-%s/maindoc/UBL-%s-%s.xsd' % (
            version, document, version)
        xsd_etree_obj = etree.parse(file_open(xsd_file))
        official_schema = etree.XMLSchema(xsd_etree_obj)
        t = etree.parse(BytesIO(xml_string))
        try:
            official_schema.assertValid(t)
        except Exception as e:
            # if the validation of the XSD fails, we arrive here
            logger = logging.getLogger(__name__)
            logger.warning(
                "The XML file is invalid against the XML Schema Definition")
            logger.warning(xml_string)
            logger.warning(e)
            raise UserError(_(
                "The UBL XML file is not valid against the official "
                "XML Schema Definition. The XML file and the "
                "full error have been written in the server logs. "
                "Here is the error, which may give you an idea on the "
                "cause of the problem : %s.")
                % str(e))
        return self._ubl_check_xml_schema_uml_extensions(t, document, version=version)

@github-actions
Copy link

There hasn't been any activity on this issue in the past 6 months, so it has been marked as stale and it will be closed automatically if no further activity occurs in the next 30 days.
If you want this issue to never become stale, please ask a PSC member to apply the "no stale" label.

@github-actions github-actions bot added the stale PR/Issue without recent activity, it'll be soon closed automatically. label Jan 30, 2022
@github-actions github-actions bot closed this as completed Mar 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stale PR/Issue without recent activity, it'll be soon closed automatically.
Projects
None yet
Development

No branches or pull requests

1 participant