se adiciona FachoXML.set_element_validator para validar contenido y attributos de elementos
FossilOrigin-Name: 0212899abf1632256a040252e45b1fc6d294cea558c930d96af22e68c9393d47
This commit is contained in:
		| @@ -4,6 +4,12 @@ | |||||||
| from lxml import etree | from lxml import etree | ||||||
| from lxml.etree import Element, SubElement, tostring | from lxml.etree import Element, SubElement, tostring | ||||||
| import re | import re | ||||||
|  | from collections import defaultdict | ||||||
|  | from pprint import pprint | ||||||
|  |  | ||||||
|  | class FachoValueInvalid(Exception): | ||||||
|  |     def __init__(self, xpath): | ||||||
|  |         super().__init__('FachoValueInvalid invalid xpath %s' % (xpath)) | ||||||
|  |  | ||||||
|  |  | ||||||
| class FachoXMLExtension: | class FachoXMLExtension: | ||||||
| @@ -128,6 +134,7 @@ class FachoXML: | |||||||
|         self.fragment_prefix = fragment_prefix |         self.fragment_prefix = fragment_prefix | ||||||
|         self.xpath_for = {} |         self.xpath_for = {} | ||||||
|         self.extensions = [] |         self.extensions = [] | ||||||
|  |         self._validators = defaultdict(lambda: lambda v, attrs: True) | ||||||
|  |  | ||||||
|     @classmethod |     @classmethod | ||||||
|     def from_string(cls, document: str, namespaces: dict() = []) -> 'FachoXML': |     def from_string(cls, document: str, namespaces: dict() = []) -> 'FachoXML': | ||||||
| @@ -221,6 +228,20 @@ class FachoXML: | |||||||
|  |  | ||||||
|         return current_elem |         return current_elem | ||||||
|  |  | ||||||
|  |     def set_element_validator(self, xpath, validator = False): | ||||||
|  |         """ | ||||||
|  |         validador al asignar contenido a xpath indicado | ||||||
|  |  | ||||||
|  |         @param xpath ruta tipo XPath | ||||||
|  |         @param validator callback(content, attributes) | ||||||
|  |         """ | ||||||
|  |  | ||||||
|  |         key = self._path_xpath_for(xpath) | ||||||
|  |         if not validator: | ||||||
|  |             self._validators[key] = lambda v, attrs: True | ||||||
|  |         else: | ||||||
|  |             self._validators[key] = validator | ||||||
|  |          | ||||||
|     def set_element(self, xpath, content, **attrs): |     def set_element(self, xpath, content, **attrs): | ||||||
|         """ |         """ | ||||||
|         asigna contenido ubicado por ruta tipo XPATH. |         asigna contenido ubicado por ruta tipo XPATH. | ||||||
| @@ -232,6 +253,11 @@ class FachoXML: | |||||||
|         format_ = attrs.pop('format_', '%s') |         format_ = attrs.pop('format_', '%s') | ||||||
|         append_ = attrs.pop('append_', False) |         append_ = attrs.pop('append_', False) | ||||||
|         elem = self.find_or_create_element(xpath, append=append_) |         elem = self.find_or_create_element(xpath, append=append_) | ||||||
|  |         validator = self._validators[xpath] | ||||||
|  |  | ||||||
|  |         if not validator(content, attrs): | ||||||
|  |             raise FachoValueInvalid(xpath) | ||||||
|  |  | ||||||
|         if content: |         if content: | ||||||
|             self.builder.set_text(elem, format_ % content) |             self.builder.set_text(elem, format_ % content) | ||||||
|         for k, v in attrs.items(): |         for k, v in attrs.items(): | ||||||
|   | |||||||
| @@ -178,3 +178,29 @@ def test_facho_xml_replacement_for(): | |||||||
|     xml.replacement_for('./child/type', |     xml.replacement_for('./child/type', | ||||||
|                         './child/code', 'test') |                         './child/code', 'test') | ||||||
|     assert xml.tostring() == '<root><child><code>test</code></child></root>' |     assert xml.tostring() == '<root><child><code>test</code></child></root>' | ||||||
|  |  | ||||||
|  | def test_facho_xml_set_element_content_invalid_validation(): | ||||||
|  |     xml = facho.FachoXML('root') | ||||||
|  |  | ||||||
|  |     with pytest.raises(facho.FachoValueInvalid) as e: | ||||||
|  |         xml.set_element_validator('./Id', lambda text, attrs: text == 'mero') | ||||||
|  |         xml.set_element('./Id', 'bad') | ||||||
|  |  | ||||||
|  | def test_facho_xml_set_element_content_valid_validation(): | ||||||
|  |     xml = facho.FachoXML('root') | ||||||
|  |  | ||||||
|  |     xml.set_element_validator('./Id', lambda text, attrs: text == 'mero') | ||||||
|  |     xml.set_element('./Id', 'mero') | ||||||
|  |  | ||||||
|  | def test_facho_xml_set_element_attribute_invalid_validation(): | ||||||
|  |     xml = facho.FachoXML('root') | ||||||
|  |  | ||||||
|  |     with pytest.raises(facho.FachoValueInvalid) as e: | ||||||
|  |         xml.set_element_validator('./Id', lambda text, attrs: attrs['code'] == 'ABC') | ||||||
|  |         xml.set_element('./Id', 'mero', code = 'CBA') | ||||||
|  |  | ||||||
|  | def test_facho_xml_set_element_attribute_valid_validation(): | ||||||
|  |     xml = facho.FachoXML('root') | ||||||
|  |  | ||||||
|  |     xml.set_element_validator('./Id', lambda text, attrs: attrs['code'] == 'ABC') | ||||||
|  |     xml.set_element('./Id', 'mero', code = 'ABC') | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user