diff --git a/source/tests/certificados/comercio.cer b/source/tests/certificados/comercio.cer
new file mode 100644
index 0000000..471d739
Binary files /dev/null and b/source/tests/certificados/comercio.cer differ
diff --git a/source/tests/certificados/comercio.enc b/source/tests/certificados/comercio.enc
new file mode 100644
index 0000000..e2e9aa4
--- /dev/null
+++ b/source/tests/certificados/comercio.enc
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQI6siSTwKyr/QCAggA
+MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBCI0ZtyIVL+Lutw1HiX9yiABIIE
+0NVK6M/HDydtFkytzQO0x5iZGKZ4rQQOvSaPItX0k/kOUX/fcMEmHvqGs3jE+HgL
+I57mW7lxC4cM5mc746p9RQI/FYGZH7t9u3KVdL5+muJ8Khs7GRu7hWK3qFOtfdxY
+8VE+1bq+3rd2Cj464An3OVKryUC16szIfTZNXJU6Ftxaq3uSDSJRct8zG4JgTMhj
+I+W1XJxUWb+56FI2dJK3MMI8IDR7ctED9XoGBP7lksqqcUmzqolgrWppfcJNoGAF
+t5Cz6ZAZShPzhbrkZ7xweMWgHYJlghMcm40D6OTr51l4mxvIOU7vKIIswYZwn1jz
+SGfo8icrhsDRpigL5vB4y0asPHFt5AvYWx0hx0CDcxDj71s09svwuSQtTEtQdNDQ
+acrffuK2miv6sxXD8DL7+cQ7Q/fdWRhELJ8HRU98YOHVJchutF7LCcAbA/iti195
+YFr10krT5xZyCb/6J33B6UY1LXu94GfmLQA2mdTwucQd0zN5mvmrlG/SXnq5LG36
+dxyXwY4uehLunKWEJu9lX/pdVB7TuNU1sA7411x0hlHi4OepTVgCOsx5nYDWviOa
+v02pUPD/ddDtJ45u6cTDGBIeeeo9ZebVUAYz7C4FS1wEspJ/Ux10gC3NPYai7m8T
+0HjE5fUXXgeeHI6AGDwzSTFxvLgVYUHGNfvf8Xuz/6/B1JQAxUWslrcI8px2WD0j
+xgot2omFbNTZkvKAfn13lZcx8dR0K5qittVFxBwOZkGg+honwzn4TzQp8ZL3E1mQ
+2DOgquSlxgT0McUivFTera6OMXMrQSmEbwkuFZh/YN4FE7uhpqB0XKM79v4cmYkD
+ze2eX46hG9nVwFXo1jPcVbMuxzwLXmVibvSsTWidqV4CKxyZB9o+B2N00dRe1bh6
+keshRlNWz3drxDCiglKz+BV84OxizWAeCQmBKNqF9umzIM/5/Cg/KnUinG5Vcw52
+5UUiIBGN4a7NQZHtTqTLRYE9vpb/7AkniTQXeQ9ZKUAF1Z+8bkxCTW7Gdmpfku2t
++5SL1qeD3bvUlShBoONJBa21KIsjZsNxEI35n9898xufs4VoNIFzsyhMlcnkoNar
+eQ+1rYigmOeKTq3T1grHujFTjVGUe8yYvgoUQjn29LH8zJkypBkL9wmY7/KBb8xK
+ZwUguw1y0hYSReMSxKqWThrQwmtkARFu2F0lUbuEXMvDVVpSfNd7w2ij1OP1nwwL
+g0q3Sd5d+cYhAGC/FioUL4vFb38DBEjCbUeezc5l8eYNfKrU8JCGSENAv1e756Vu
+xb+7mkw/YqL6vMeqq6/S58Naz2IXCM+1iH9KuRS2xqayMCuISbyb/QtzWNnDrTPN
+/8qCHO9yijP2/1mQURCnj8lqUbr7nbp9mzuaC+eAaVFEGSfDLx1wV8mFH0rko5Lr
+/o5bs/15uCCXxfPWsbViDc+5nCnm0qvLBzUWZfps10CklvcU5Gq5f2VyBrMKyP1X
+cQnS6RogrJ6kEYTBc1/VGTTw4RKR6CnCmYNi921stLu9ayMfDroegmEPuM+59+Tn
+2Jw2mw/jL0m0stIoAgBEfc4i8a+uabtbD01yJEBnaTomfUUJNckJf3RPZrnDYmGr
+lOaDNKIu+f1GcLrahHqbXXVTGVVGqezOUn/IdYubufYw
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/source/tests/certificados/comercio.key b/source/tests/certificados/comercio.key
new file mode 100644
index 0000000..0155f0a
Binary files /dev/null and b/source/tests/certificados/comercio.key differ
diff --git a/source/tests/pycert/__init__.py b/source/tests/pycert/__init__.py
new file mode 100644
index 0000000..dbe4529
--- /dev/null
+++ b/source/tests/pycert/__init__.py
@@ -0,0 +1,3 @@
+#!/usr/bin/env python3
+
+from .cfdi_cert import SATCertificate
diff --git a/source/tests/pycert/cfdi_cert.py b/source/tests/pycert/cfdi_cert.py
new file mode 100644
index 0000000..c493b88
--- /dev/null
+++ b/source/tests/pycert/cfdi_cert.py
@@ -0,0 +1,255 @@
+#!/usr/bin/env python3
+
+import argparse
+import base64
+import datetime
+import getpass
+from pathlib import Path
+
+import xmlsec
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives import serialization
+from cryptography import x509
+from cryptography.x509.oid import NameOID
+from cryptography.x509.oid import ExtensionOID
+from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives.asymmetric import padding
+
+from .conf import TOKEN
+
+
+class SATCertificate(object):
+
+ def __init__(self, cer=b'', key=b'', password=''):
+ self._error = ''
+ self._init_values()
+ self._get_data_cer(cer)
+ self._get_data_key(key, password)
+
+ def _init_values(self):
+ self._rfc = ''
+ self._serial_number = ''
+ self._not_before = None
+ self._not_after = None
+ self._is_fiel = False
+ self._are_couple = False
+ self._is_valid_time = False
+ self._cer_pem = ''
+ self._cer_txt = ''
+ self._key_enc = b''
+ self._p12 = b''
+ self._cer_modulus = 0
+ self._key_modulus = 0
+ return
+
+ def __str__(self):
+ msg = '\tRFC: {}\n'.format(self.rfc)
+ msg += '\tNo de Serie: {}\n'.format(self.serial_number)
+ msg += '\tVálido desde: {}\n'.format(self.not_before)
+ msg += '\tVálido hasta: {}\n'.format(self.not_after)
+ msg += '\tEs vigente: {}\n'.format(self.is_valid_time)
+ msg += '\tSon pareja: {}\n'.format(self.are_couple)
+ msg += '\tEs FIEL: {}\n'.format(self.is_fiel)
+ return msg
+
+ def __bool__(self):
+ return self.is_valid
+
+ def _get_hash(self):
+ digest = hashes.Hash(hashes.SHA512(), default_backend())
+ digest.update(self._rfc.encode())
+ digest.update(self._serial_number.encode())
+ digest.update(TOKEN.encode())
+ return digest.finalize()
+
+ def _get_data_cer(self, cer):
+ obj = x509.load_der_x509_certificate(cer, default_backend())
+ self._rfc = obj.subject.get_attributes_for_oid(
+ NameOID.X500_UNIQUE_IDENTIFIER)[0].value.split(' ')[0]
+ self._serial_number = '{0:x}'.format(obj.serial_number)[1::2]
+ self._not_before = obj.not_valid_before
+ self._not_after = obj.not_valid_after
+ now = datetime.datetime.utcnow()
+ self._is_valid_time = (now > self.not_before) and (now < self.not_after)
+ if not self._is_valid_time:
+ msg = 'El certificado no es vigente'
+ self._error = msg
+
+ self._is_fiel = obj.extensions.get_extension_for_oid(
+ ExtensionOID.KEY_USAGE).value.key_agreement
+
+ self._cer_pem = obj.public_bytes(serialization.Encoding.PEM).decode()
+ self._cer_txt = ''.join(self._cer_pem.split('\n')[1:-2])
+ self._cer_modulus = obj.public_key().public_numbers().n
+ return
+
+ def _get_data_key(self, key, password):
+ self._key_enc = key
+ if not key or not password:
+ return
+
+ try:
+ obj = serialization.load_der_private_key(
+ key, password.encode(), default_backend())
+ except ValueError:
+ msg = 'La contraseña es incorrecta'
+ self._error = msg
+ return
+
+ p = self._get_hash()
+ self._key_enc = obj.private_bytes(
+ encoding=serialization.Encoding.PEM,
+ format=serialization.PrivateFormat.PKCS8,
+ encryption_algorithm=serialization.BestAvailableEncryption(p)
+ )
+
+ self._key_modulus = obj.public_key().public_numbers().n
+ self._are_couple = self._cer_modulus == self._key_modulus
+ if not self._are_couple:
+ msg = 'El CER y el KEY no son pareja'
+ self._error = msg
+ return
+
+ def _get_key(self, password):
+ if not password:
+ password = self._get_hash()
+ private_key = serialization.load_pem_private_key(
+ self._key_enc, password=password, backend=default_backend())
+ return private_key
+
+ def _get_key_pem(self):
+ obj = self._get_key('')
+ key_pem = obj.private_bytes(
+ encoding=serialization.Encoding.PEM,
+ format=serialization.PrivateFormat.PKCS8,
+ encryption_algorithm=serialization.NoEncryption()
+ )
+ return key_pem
+
+ # Not work
+ def _get_p12(self):
+ obj = serialization.pkcs12.serialize_key_and_certificates('test',
+ self.key_pem, self.cer_pem, None,
+ encryption_algorithm=serialization.NoEncryption()
+ )
+ return obj
+
+ def sign(self, data, password=''):
+ private_key = self._get_key(password)
+ firma = private_key.sign(data, padding.PKCS1v15(), hashes.SHA256())
+ return base64.b64encode(firma).decode()
+
+ def sign_xml(self, tree):
+ node = xmlsec.tree.find_node(tree, xmlsec.constants.NodeSignature)
+ ctx = xmlsec.SignatureContext()
+ key = xmlsec.Key.from_memory(self.key_pem, xmlsec.constants.KeyDataFormatPem)
+ ctx.key = key
+ ctx.sign(node)
+ node = xmlsec.tree.find_node(tree, 'X509Certificate')
+ node.text = self.cer_txt
+ return tree
+
+ @property
+ def rfc(self):
+ return self._rfc
+
+ @property
+ def serial_number(self):
+ return self._serial_number
+
+ @property
+ def not_before(self):
+ return self._not_before
+
+ @property
+ def not_after(self):
+ return self._not_after
+
+ @property
+ def is_fiel(self):
+ return self._is_fiel
+
+ @property
+ def are_couple(self):
+ return self._are_couple
+
+ @property
+ def is_valid(self):
+ return not bool(self.error)
+
+ @property
+ def is_valid_time(self):
+ return self._is_valid_time
+
+ @property
+ def cer_pem(self):
+ return self._cer_pem.encode()
+
+ @property
+ def cer_txt(self):
+ return self._cer_txt
+
+ @property
+ def key_pem(self):
+ return self._get_key_pem()
+
+ @property
+ def key_enc(self):
+ return self._key_enc
+
+ @property
+ def p12(self):
+ return self._get_p12()
+
+ @property
+ def error(self):
+ return self._error
+
+
+def main(args):
+ # ~ contra = getpass.getpass('Introduce la contraseña del archivo KEY: ')
+ contra = '12345678a'
+ if not contra.strip():
+ msg = 'La contraseña es requerida'
+ print(msg)
+ return
+
+ path_cer = Path(args.cer)
+ path_key = Path(args.key)
+
+ if not path_cer.is_file():
+ msg = 'El archivo CER es necesario'
+ print(msg)
+ return
+
+ if not path_key.is_file():
+ msg = 'El archivo KEY es necesario'
+ print(msg)
+ return
+
+ cer = path_cer.read_bytes()
+ key = path_key.read_bytes()
+ cert = SATCertificate(cer, key, contra)
+
+ if cert.error:
+ print(cert.error)
+ else:
+ print(cert)
+ return
+
+
+def _process_command_line_arguments():
+ parser = argparse.ArgumentParser(description='CFDI Certificados')
+
+ help = 'Archivo CER'
+ parser.add_argument('-c', '--cer', help=help, default='')
+ help = 'Archivo KEY'
+ parser.add_argument('-k', '--key', help=help, default='')
+
+ args = parser.parse_args()
+ return args
+
+
+if __name__ == '__main__':
+ args = _process_command_line_arguments()
+ main(args)
diff --git a/source/tests/pycert/conf.py.example b/source/tests/pycert/conf.py.example
new file mode 100644
index 0000000..4e350fb
--- /dev/null
+++ b/source/tests/pycert/conf.py.example
@@ -0,0 +1,7 @@
+#!/usr/bin/env python3
+
+# ~ Establece un token personalizado para encriptar las claves
+# ~ from secrets import token_hex
+# ~ token_hex(32)
+
+TOKEN = ''
diff --git a/source/tests/tests_comercio.py b/source/tests/tests_comercio.py
new file mode 100644
index 0000000..831d9ee
--- /dev/null
+++ b/source/tests/tests_comercio.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env python3
+
+import datetime
+import sys
+import unittest
+import uuid
+import lxml.etree as ET
+from io import BytesIO
+from pathlib import Path
+
+sys.path.append('..')
+from pycert import SATCertificate
+from comerciodigital import PACComercioDigital
+
+
+NAME = 'comercio'
+
+TEMPLATE_CFDI = """
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+"""
+
+class TestCfdi(object):
+
+ def __init__(self):
+ self._xml = ''
+ self._make_cfdi()
+
+ @property
+ def xml(self):
+ return self._xml.decode()
+
+ def _make_cfdi(self):
+ path = Path(__file__)
+ path_cer = Path(path.parent).joinpath('certificados', f'{NAME}.cer')
+ path_key = Path(path.parent).joinpath('certificados', f'{NAME}.enc')
+ path_xslt = Path(path.parent).joinpath('xslt', 'cadena.xslt')
+ cer = path_cer.read_bytes()
+ key = path_key.read_bytes()
+
+ self._cert = SATCertificate(cer, key)
+ self._doc = ET.parse(BytesIO(TEMPLATE_CFDI.encode()))
+ self._root = self._doc.getroot()
+ self._root.attrib['Fecha'] = datetime.datetime.now().isoformat()[:19]
+ self._root.attrib['NoCertificado'] = self._cert.serial_number
+ self._root.attrib['Certificado'] = self._cert.cer_txt
+
+ self._add_stamp(path_xslt)
+
+ self._xml = ET.tostring(self._root,
+ pretty_print=True, doctype='')
+ return
+
+ def _add_stamp(self, path_xslt):
+ xslt = open(path_xslt, 'rb')
+ transfor = ET.XSLT(ET.parse(xslt))
+ cadena = str(transfor(self._doc)).encode()
+ stamp = self._cert.sign(cadena)
+ self._root.attrib['Sello'] = stamp
+ xslt.close()
+ return
+
+
+class TestStamp(unittest.TestCase):
+
+ def setUp(self):
+ print(f'In method: {self._testMethodName}')
+ self.pac = PACComercioDigital()
+
+ def test_cfdi_stamp(self):
+ cfdi = TestCfdi().xml
+ result = self.pac.stamp(cfdi)
+ cfdi_uuid = self.pac.cfdi_uuid
+
+ self.assertFalse(bool(self.pac.error))
+ self.assertTrue(bool(uuid.UUID(cfdi_uuid)))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/source/tests/xslt/cadena.xslt b/source/tests/xslt/cadena.xslt
new file mode 100644
index 0000000..4c6e2d5
--- /dev/null
+++ b/source/tests/xslt/cadena.xslt
@@ -0,0 +1,345 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |||
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/tests/xslt/comercioexterior11.xslt b/source/tests/xslt/comercioexterior11.xslt
new file mode 100644
index 0000000..fd71841
--- /dev/null
+++ b/source/tests/xslt/comercioexterior11.xslt
@@ -0,0 +1,181 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/tests/xslt/divisas.xslt b/source/tests/xslt/divisas.xslt
new file mode 100644
index 0000000..dc8988e
--- /dev/null
+++ b/source/tests/xslt/divisas.xslt
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/tests/xslt/donat11.xslt b/source/tests/xslt/donat11.xslt
new file mode 100644
index 0000000..24d4363
--- /dev/null
+++ b/source/tests/xslt/donat11.xslt
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/tests/xslt/iedu.xslt b/source/tests/xslt/iedu.xslt
new file mode 100644
index 0000000..eb285cb
--- /dev/null
+++ b/source/tests/xslt/iedu.xslt
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/tests/xslt/implocal.xslt b/source/tests/xslt/implocal.xslt
new file mode 100644
index 0000000..80b8d23
--- /dev/null
+++ b/source/tests/xslt/implocal.xslt
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/tests/xslt/ine11.xslt b/source/tests/xslt/ine11.xslt
new file mode 100644
index 0000000..05c1e56
--- /dev/null
+++ b/source/tests/xslt/ine11.xslt
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source/tests/xslt/leyendasFisc.xslt b/source/tests/xslt/leyendasFisc.xslt
new file mode 100644
index 0000000..e0587a2
--- /dev/null
+++ b/source/tests/xslt/leyendasFisc.xslt
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/tests/xslt/nomina12.xslt b/source/tests/xslt/nomina12.xslt
new file mode 100644
index 0000000..2570170
--- /dev/null
+++ b/source/tests/xslt/nomina12.xslt
@@ -0,0 +1,412 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source/tests/xslt/pagos10.xslt b/source/tests/xslt/pagos10.xslt
new file mode 100644
index 0000000..98b41f2
--- /dev/null
+++ b/source/tests/xslt/pagos10.xslt
@@ -0,0 +1,165 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/tests/xslt/utilerias.xslt b/source/tests/xslt/utilerias.xslt
new file mode 100644
index 0000000..d5dd14e
--- /dev/null
+++ b/source/tests/xslt/utilerias.xslt
@@ -0,0 +1,22 @@
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+