You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

224 lines
9.5 KiB

# vim: fileencoding=utf-8
#
from pyparsing import originalTextFor, Literal, Word, printables, OneOrMore,\
Optional
from .base_format import BaseFormat
from collections import OrderedDict
try:
from lxml.etree import Element, SubElement, ElementTree, tostring
except ImportError:
from xml.etree.ElementTree import Element, SubElement, ElementTree, \
tostring
class XMLGConfFormat(BaseFormat):
def __init__(self, document_text: str):
processing_methods = OrderedDict({'gconf': self._gconf,
'entry': self._entry,
'dir': self._dir,
'stringvalue': self._stringvalue,
'default': self._default,
'local_schema': self._local_schema,
'li': self._li,
'longdesc': self._longdesc,
'unknown': self._unknown})
super().__init__(processing_methods)
self._format = 'xml_gconf'
self._initialize_parser()
self._parse_xml_to_dictionary(document_text)
def _initialize_parser(self):
action_symbols = (Literal('!') | Literal('-'))
name = originalTextFor(OneOrMore(Word(printables)))
self._node_name = Optional(action_symbols)('action') + name('name')
def _entry(self, xml_element):
try:
element_items = OrderedDict(xml_element.attrib)
name = element_items.pop('name')
parsing_result = self._node_name.parseString(name)
if 'value' in element_items:
entry_value = element_items.pop('value')
elif 'ltype' in element_items:
entry_value = []
for child in xml_element:
item_to_add = self._processing_methods.get(child.tag,
self._unknown
)(child)
entry_value.append(item_to_add)
else:
entry_value = OrderedDict()
for child in xml_element:
item_to_add = self._processing_methods.get(child.tag,
self._unknown
)(child)
entry_value.update(item_to_add)
element_name = (parsing_result.action,
xml_element.tag,
('name', parsing_result.name),
*element_items.items())
return OrderedDict({element_name: entry_value})
except Exception:
# Какая-то обработка ошибки.
return OrderedDict()
def _gconf(self, xml_element):
output_dictionary = OrderedDict()
element_name = ('', xml_element.tag)
for child in xml_element:
item_to_add = self._processing_methods.get(child.tag,
self._unknown)(child)
output_dictionary.update(item_to_add)
return OrderedDict({element_name: output_dictionary})
def _dir(self, xml_element):
output_dictionary = OrderedDict()
try:
parsing_result = self._node_name.parseString(
xml_element.attrib['name']
)
element_name = (parsing_result.action,
xml_element.tag,
('name', parsing_result.name))
except Exception:
# Какая-то обработка ошибки.
return OrderedDict()
for child in xml_element:
item_to_add = self._processing_methods.get(child.tag,
self._unknown)(child)
output_dictionary.update(item_to_add)
return OrderedDict({element_name: output_dictionary})
def _longdesc(self, xml_element):
element_name = ('', 'longdesc')
description = xml_element.text
if description is not None:
return OrderedDict({element_name: description})
else:
# Пустая строка. Возможно ошибка.
# Какая-то обработка ошибки.
return OrderedDict({element_name: ''})
def _local_schema(self, xml_element):
output_dictionary = OrderedDict()
try:
element_name = ('', xml_element.tag,
*xml_element.items())
except Exception:
# Какая-то обработка ошибки.
return OrderedDict()
for child in xml_element:
item_to_add = self._processing_methods.get(child.tag,
self._unknown)(child)
output_dictionary.update(item_to_add)
return OrderedDict({element_name: output_dictionary})
def _stringvalue(self, xml_element):
element_name = ('', 'stringvalue')
value = xml_element.text
if value is not None:
return OrderedDict({element_name: value})
else:
# Пустая строка. Возможно ошибка.
# Какая-то обработка ошибки.
return OrderedDict({element_name: ''})
def _default(self, xml_element):
output_dictionary = OrderedDict()
element_name = ('', xml_element.tag, *xml_element.items())
for child in xml_element:
item_to_add = self._processing_methods.get(child.tag,
self._unknown)(child)
output_dictionary.update(item_to_add)
return OrderedDict({element_name: output_dictionary})
def _li(self, xml_element):
child = next(iter(xml_element))
list_element = self._processing_methods.get(child.tag,
self._unknown)(child)
# Единственным возможным типом списковых значений пока является string.
string_value = next(iter(list_element.values()))
return string_value
def _unknown(self, xml_element):
# Действия если элемент неизвестен.
element_name = ('', Element.tag)
return OrderedDict({element_name: 'Unknown element'})
def get_document_text(self):
gconf_header = next(iter(self._document_dictionary))
root = Element('gconf')
self._build_section(root, self._document_dictionary[gconf_header])
document_tree = ElementTree(root)
xml_document = tostring(document_tree,
encoding="UTF-8",
xml_declaration=True,
pretty_print=True).decode()
return xml_document
def _build_section(self, current_element, dictionary):
for dict_element in dictionary.keys():
element_tag = dict_element[1]
element_attributes = OrderedDict({key: value for key, value in
dict_element[2:]})
if element_tag == 'dir' or element_tag == 'local_schema'\
or element_tag == 'default':
include_element = SubElement(current_element,
element_tag,
**element_attributes)
self._build_section(include_element,
dictionary[dict_element])
elif element_tag == 'entry':
if isinstance(dictionary[dict_element], OrderedDict):
include_element = SubElement(current_element,
element_tag,
**element_attributes)
self._build_section(include_element,
dictionary[dict_element])
elif 'ltype' in element_attributes:
if element_attributes['ltype'] == 'string':
entry_element = SubElement(current_element,
element_tag,
**element_attributes)
for value in dictionary[dict_element]:
list_element = SubElement(entry_element,
'li', type='string')
include_element = SubElement(list_element,
'stringvalue')
include_element.text = value
else:
include_element = SubElement(current_element,
element_tag,
**element_attributes,
value=dictionary[dict_element]
)
elif element_tag == 'longdesc' or element_tag == 'stringvalue':
include_element = SubElement(current_element,
element_tag)
include_element.text = dictionary[dict_element]