se adiciona FachoXML.set_element_validator para validar contenido y attributos de elementos

FossilOrigin-Name: 0212899abf1632256a040252e45b1fc6d294cea558c930d96af22e68c9393d47
This commit is contained in:
bit4bit 2021-11-02 13:57:18 +00:00
parent f627e3e22a
commit fcd5060485
2 changed files with 52 additions and 0 deletions

View File

@ -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():

View File

@ -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')