xmlhandler.py 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. from lxml import etree
  2. from helpers.xadessigner import XAdESSigner, XaDESSignerException
  3. from copy import deepcopy
  4. import unicodedata
  5. import string
  6. class XMLHandler:
  7. def __init__(self, xml_file, xml_reference_type):
  8. self.xml_file = xml_file
  9. self.xml_tree = self.__parse_xml(xml_file)
  10. self.xml_reference_type = xml_reference_type
  11. def __parse_xml(self, xml_file):
  12. try:
  13. xml_tree = etree.parse(xml_file)
  14. return xml_tree
  15. except:
  16. raise XMLHandlerException('Input XML is invalid.')
  17. def valid(self, xml_schema):
  18. try:
  19. xml_schema_tree = etree.XMLSchema(etree.parse(xml_schema))
  20. return xml_schema_tree.validate(self.xml_tree)
  21. except:
  22. return False
  23. def sign(self, certificate_file, certificate_password):
  24. try:
  25. xml_signer = XAdESSigner(deepcopy(self.xml_tree.getroot()), self.xml_reference_type, certificate_file)
  26. xml_signed_tree = xml_signer.sign(certificate_password)
  27. with open(self.xml_file, 'wb') as signed_xml:
  28. etree.ElementTree(xml_signed_tree).write(signed_xml, encoding='utf-8', xml_declaration=True)
  29. except IOError:
  30. raise XMLHandlerException('Problem with writing signed XML file.')
  31. except XaDESSignerException as e:
  32. raise XMLHandlerException(str(e))
  33. except:
  34. raise XMLHandlerException('Something went wrong with writing signed XML file.')
  35. def get_general_filename(self):
  36. default_filename = 'document'
  37. xml_root = self.xml_tree.getroot()
  38. if xml_root is not None and len(xml_root) > 0 and len(xml_root[0]) > 0 and len(xml_root[0][0]) > 1:
  39. return self.__normalize_filename(xml_root[0][0][1].text.strip(), default_filename)
  40. return default_filename
  41. def __normalize_filename(self, filename, default_filename='document'):
  42. if len(filename) == 0:
  43. return default_filename
  44. valid_chars = '-_%s%s' % (string.ascii_letters, string.digits)
  45. replacement_char = '_'
  46. clean_name = unicodedata.normalize('NFKD', filename).encode('ascii', 'ignore').decode('utf-8')
  47. return ''.join(c.lower() if c in valid_chars else replacement_char for c in clean_name)
  48. class XMLHandlerException(Exception):
  49. pass