facho placeholder mantiene orden de elementos

FossilOrigin-Name: c535b486c8f956a25f8e88bf9053aab312ed441b1d217699a36924e24b46ab21
This commit is contained in:
bit4bit 2021-11-04 02:31:45 +00:00
parent adbd6d0d0e
commit 7f72bab06a
2 changed files with 60 additions and 3 deletions

View File

@ -5,6 +5,7 @@ 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 collections import defaultdict
from copy import deepcopy
from pprint import pprint from pprint import pprint
class FachoValueInvalid(Exception): class FachoValueInvalid(Exception):
@ -114,9 +115,18 @@ class LXMLBuilder:
elem.attrib[key] = value elem.attrib[key] = value
@classmethod @classmethod
def tostring(self, elem, **attrs): def tostring(self, oelem, **attrs):
elem = deepcopy(oelem)
attrs['pretty_print'] = attrs.pop('pretty_print', False) attrs['pretty_print'] = attrs.pop('pretty_print', False)
attrs['encoding'] = attrs.pop('encoding', 'UTF-8') attrs['encoding'] = attrs.pop('encoding', 'UTF-8')
for el in elem.getiterator():
is_optional = el.get('facho_optional', 'False') == 'True'
if is_optional and el.getchildren() == []:
print(tostring(el))
el.getparent().remove(el)
return tostring(elem, **attrs).decode('utf-8') return tostring(elem, **attrs).decode('utf-8')
@ -182,8 +192,11 @@ class FachoXML:
def _path_xpath_for(self, xpath): def _path_xpath_for(self, xpath):
return self._normalize_xpath(self._translate_xpath_for(xpath)) return self._normalize_xpath(self._translate_xpath_for(xpath))
def placeholder_for(self, xpath, append=False): def placeholder_for(self, xpath, append=False, optional=False):
return self.find_or_create_element(xpath, append) elem = self.find_or_create_element(xpath, append)
if optional:
elem.set('facho_optional', 'True')
return elem
def replacement_for(self, xpath, new_xpath, content, **attrs): def replacement_for(self, xpath, new_xpath, content, **attrs):
elem = self.get_element(xpath) elem = self.get_element(xpath)
@ -217,6 +230,7 @@ class FachoXML:
for node_path in node_paths: for node_path in node_paths:
node_expr = self.builder.match_expression(node_path) node_expr = self.builder.match_expression(node_path)
node = self.builder.build_from_expression(node_path) node = self.builder.build_from_expression(node_path)
child = self.builder.find_relative(current_elem, node_expr['path'], self.nsmap) child = self.builder.find_relative(current_elem, node_expr['path'], self.nsmap)
parent = current_elem parent = current_elem
@ -240,6 +254,12 @@ class FachoXML:
self.builder.append_next(last_slibing, node) self.builder.append_next(last_slibing, node)
return node return node
try:
# TODO(bit4bit) acoplamiento indirecto a placeholder
del current_elem.attrib['facho_optional']
except KeyError:
pass
return current_elem return current_elem
def set_element_validator(self, xpath, validator = False): def set_element_validator(self, xpath, validator = False):
@ -267,6 +287,7 @@ 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] validator = self._validators[xpath]
if not validator(content, attrs): if not validator(content, attrs):

View File

@ -219,3 +219,39 @@ def test_facho_xml_keep_orden_slibing():
xml.find_or_create_element('./A', append=True) xml.find_or_create_element('./A', append=True)
assert xml.tostring() == '<root><A/><A/><B/><B/><C/></root>' assert xml.tostring() == '<root><A/><A/><B/><B/><C/></root>'
def test_facho_xml_placeholder_optional():
xml = facho.FachoXML('root')
xml.placeholder_for('./A')
xml.placeholder_for('./B', optional=True)
xml.placeholder_for('./C')
assert xml.tostring() == '<root><A/><C/></root>'
def test_facho_xml_placeholder_append_to_optional():
xml = facho.FachoXML('root')
xml.placeholder_for('./A')
xml.placeholder_for('./B', optional=True)
xml.placeholder_for('./C')
xml.find_or_create_element('./B')
assert xml.tostring() == '<root><A/><B/><C/></root>'
def test_facho_xml_placeholder_set_element_to_optional():
xml = facho.FachoXML('root')
xml.placeholder_for('./A')
xml.placeholder_for('./B', optional=True)
xml.placeholder_for('./C')
xml.set_element('./B', '2')
assert xml.tostring() == '<root><A/><B>2</B><C/></root>'
def test_facho_xml_placeholder_set_element_to_optional_with_append():
xml = facho.FachoXML('root')
xml.placeholder_for('./A')
xml.placeholder_for('./B', optional=True)
xml.placeholder_for('./C')
xml.set_element('./B', '2')
xml.set_element('./B', '3', append_=True)
assert xml.tostring() == '<root><A/><B>2</B><B>3</B><C/></root>'