# Path: src/sii/lib/schemas.py
# def resolve_schema(xml):
#     """ Resolves the schema based on the root node's tag
# 
#     :param `etree.Element` tag_name: The root node of the XML in question.
# 
#     :return: A string containing the path to the correponding schema for validation.
#     """
#     if hasattr(xml, 'getroot'):
#         root = xml.getroot()
#     else:
#         root = xml.getroottree().getroot()
# 
#     try:
#         path = SCHEMA_FILES[root.tag]
#     except KeyError as exc:
#         raise KeyError("Could not find schema for root tag '{0}'".format(root.tag)) from exc
#     else:
#         return path
# 
# Path: src/sii/lib/helpers.py
# def prepend_dtd(xml):
#     """ Prepends a DTD providing a definition of a to a non-standard xml:id pointer. Necessary for
#     signature and signature verification.
# 
#     :param `etree.Element` xml: XML tree to prepend the DTD to.
# 
#     :param str sig_tag:   Tag name to contain the URI.
#     :param str uri_attr:  Attribute name to contain the URI.
# 
#     :return: An `etree.Element` with the now DTD contextualized XML.
#     """
#     root = None
#     if hasattr(xml, 'getroot'):
#         root = xml.getroot()
#     else:
#         root = xml.getroottree().getroot()
# 
#     tag      = re.sub('\{.*\}', '', root.tag)
#     preamble = DTD_PREAMBLE.format(root=tag)
# 
#     buff = io.BytesIO()
#     buff.write(bytes(preamble, 'utf8'))
#     buff.write(etree.tostring(xml, pretty_print=True, method='xml'))
#     buff.seek(0)
# 
#     tree = etree.parse(buff)
#     root = tree.getroot()
# 
#     return root
# 
# def extract_signodes(xml):
#     """ Extracts all <ds:Signature> nodes from given XML.
# 
#     :param `etree.Element` xml: Root node of the document.
# 
#     :return: list of `etree.Element` of the <ds:Signature>'s
#     """
#     signodes = xml.xpath('//ds:Signature', namespaces={'ds': 'http://www.w3.org/2000/09/xmldsig#'})
#     return signodes
# 
# def extract_signode_certificate(signode):
#     """ Extract the x509 Certificate Information from a <ds:Signature>.
# 
#     Raises exception if it does not find any <X509Certificate> information in the <Signature>.
# 
#     :param `etree.Element` signode: Root node of the document.
# 
#     :return: UTF8 encoded string containing the base64 encoded PEM certificate in it.
#     """
#     cert_node = signode.find('.//{http://www.w3.org/2000/09/xmldsig#}X509Certificate')
#     cert_text = ''
# 
#     if cert_node is None:
#         raise ValueError("Could not find x509 certificate on this signode")
#     else:
#         cert_text = cert_node.text
# 
#     buff  = '-----BEGIN CERTIFICATE-----\n'
#     buff += cert_text.strip('\n')
#     buff += '\n-----END CERTIFICATE-----\n'
# 
#     return buff
# 
# def extract_signode_reference(signode):
#     """ Extracts the <ds:Reference> of a <ds:Signature> node.
# 
#     :param `etree.Element` xml: Root node of the document.
# 
#     :return: `etree.Element` of the <ds:Reference>
#     """
#     refs = signode.xpath('.//ds:Reference', namespaces={'ds': 'http://www.w3.org/2000/09/xmldsig#'})
# 
#     if len(refs) != 1:
#         raise ValueError("Could not find x509 reference on this signode")
#     else:
#         return refs[0]


from io   import BytesIO
from copy import deepcopy
from lxml import etree
from .schemas import resolve_schema
from .helpers import (
    prepend_dtd,
    extract_signodes,
    extract_signode_certificate,
    extract_signode_reference,
)
import tempfile
import xmlsec
        ctx = xmlsec.SignatureContext(key_mgr)

        try:
            ctx.verify(signode)
        except xmlsec.error.Error:
            validity = (ref.attrib['URI'], False)
        else:
            validity = (ref.attrib['URI'], True)

        results.append(validity)

    return results


def validate_schema(doc_xml, schema_xml=None):
    """ Validate XML against its XSD Schema definition provided by the SII.

    :param `lxml.etree.Element` doc_xml: Handle to XML etree root node.
    """
    doc_xml = deepcopy(doc_xml)

    doc_new    = etree.Element(doc_xml.tag, nsmap={None: 'http://www.sii.cl/SiiDte'})
    doc_new[:] = doc_xml[:]                # move children into new root
    doc_new.attrib.update(doc_xml.attrib)  # copy attributes of the root node

    # reload xml
    buff = BytesIO(etree.tostring(doc_new, method='c14n'))
    xml  = etree.parse(buff).getroot()

    if not schema_xml:

# Path: src/sii/lib/schemas.py
# def resolve_schema(xml):
#     """ Resolves the schema based on the root node's tag
# 
#     :param `etree.Element` tag_name: The root node of the XML in question.
# 
#     :return: A string containing the path to the correponding schema for validation.
#     """
#     if hasattr(xml, 'getroot'):
#         root = xml.getroot()
#     else:
#         root = xml.getroottree().getroot()
# 
#     try:
#         path = SCHEMA_FILES[root.tag]
#     except KeyError as exc:
#         raise KeyError("Could not find schema for root tag '{0}'".format(root.tag)) from exc
#     else:
#         return path
# 
# Path: src/sii/lib/helpers.py
# def prepend_dtd(xml):
#     """ Prepends a DTD providing a definition of a to a non-standard xml:id pointer. Necessary for
#     signature and signature verification.
# 
#     :param `etree.Element` xml: XML tree to prepend the DTD to.
# 
#     :param str sig_tag:   Tag name to contain the URI.
#     :param str uri_attr:  Attribute name to contain the URI.
# 
#     :return: An `etree.Element` with the now DTD contextualized XML.
#     """
#     root = None
#     if hasattr(xml, 'getroot'):
#         root = xml.getroot()
#     else:
#         root = xml.getroottree().getroot()
# 
#     tag      = re.sub('\{.*\}', '', root.tag)
#     preamble = DTD_PREAMBLE.format(root=tag)
# 
#     buff = io.BytesIO()
#     buff.write(bytes(preamble, 'utf8'))
#     buff.write(etree.tostring(xml, pretty_print=True, method='xml'))
#     buff.seek(0)
# 
#     tree = etree.parse(buff)
#     root = tree.getroot()
# 
#     return root
# 
# def extract_signodes(xml):
#     """ Extracts all <ds:Signature> nodes from given XML.
# 
#     :param `etree.Element` xml: Root node of the document.
# 
#     :return: list of `etree.Element` of the <ds:Signature>'s
#     """
#     signodes = xml.xpath('//ds:Signature', namespaces={'ds': 'http://www.w3.org/2000/09/xmldsig#'})
#     return signodes
# 
# def extract_signode_certificate(signode):
#     """ Extract the x509 Certificate Information from a <ds:Signature>.
# 
#     Raises exception if it does not find any <X509Certificate> information in the <Signature>.
# 
#     :param `etree.Element` signode: Root node of the document.
# 
#     :return: UTF8 encoded string containing the base64 encoded PEM certificate in it.
#     """
#     cert_node = signode.find('.//{http://www.w3.org/2000/09/xmldsig#}X509Certificate')
#     cert_text = ''
# 
#     if cert_node is None:
#         raise ValueError("Could not find x509 certificate on this signode")
#     else:
#         cert_text = cert_node.text
# 
#     buff  = '-----BEGIN CERTIFICATE-----\n'
#     buff += cert_text.strip('\n')
#     buff += '\n-----END CERTIFICATE-----\n'
# 
#     return buff
# 
# def extract_signode_reference(signode):
#     """ Extracts the <ds:Reference> of a <ds:Signature> node.
# 
#     :param `etree.Element` xml: Root node of the document.
# 
#     :return: `etree.Element` of the <ds:Reference>
#     """
#     refs = signode.xpath('.//ds:Reference', namespaces={'ds': 'http://www.w3.org/2000/09/xmldsig#'})
# 
#     if len(refs) != 1:
#         raise ValueError("Could not find x509 reference on this signode")
#     else:
#         return refs[0]


# Path: src/sii/lib/validation.py
from io   import BytesIO
from copy import deepcopy
from lxml import etree
from .schemas import resolve_schema
from .helpers import (
    prepend_dtd,
    extract_signodes,
    extract_signode_certificate,
    extract_signode_reference,
)
import tempfile
import xmlsec

        ctx = xmlsec.SignatureContext(key_mgr)

        try:
            ctx.verify(signode)
        except xmlsec.error.Error:
            validity = (ref.attrib['URI'], False)
        else:
            validity = (ref.attrib['URI'], True)

        results.append(validity)

    return results


def validate_schema(doc_xml, schema_xml=None):
    """ Validate XML against its XSD Schema definition provided by the SII.

    :param `lxml.etree.Element` doc_xml: Handle to XML etree root node.
    """
    doc_xml = deepcopy(doc_xml)

    doc_new    = etree.Element(doc_xml.tag, nsmap={None: 'http://www.sii.cl/SiiDte'})
    doc_new[:] = doc_xml[:]                # move children into new root
    doc_new.attrib.update(doc_xml.attrib)  # copy attributes of the root node

    # reload xml
    buff = BytesIO(etree.tostring(doc_new, method='c14n'))
    xml  = etree.parse(buff).getroot()

    if not schema_xml:

        schema_pth = resolve_schema(doc_xml)