diff --git a/pym/cl_profile.py b/pym/cl_profile.py index c5137c7..98d41f9 100644 --- a/pym/cl_profile.py +++ b/pym/cl_profile.py @@ -26,6 +26,7 @@ import types import copy import random import string +import time tr = cl_base.lang() tr.setLocalDomain('cl_lib') @@ -5864,7 +5865,7 @@ Valid values attribute 'action': \ self._removeDropNodesAndAttrAction(self.bodyNode) def _join(self, xmlNewNode, xmlOldNode, flagRootNode=True): - """Объединение корневой ноды профиля и корненвой ноды файла""" + """Объединение корневой ноды профиля и корневой ноды файла""" xmlNode = xmlNewNode childNodes = xmlNode.childNodes nextOldNode = xmlOldNode @@ -5995,7 +5996,7 @@ the same nodes at one level") return False # Импортируем корневую ноду нового документа в текущий документ #newImportBodyNode = self.doc.importNode(doc.documentElement, True) - # Объединение корневой ноды профиля и корненвой ноды файла + # Объединение корневой ноды профиля и корневой ноды файла if not self._join(doc.documentElement, self.bodyNode): return False return True @@ -6103,7 +6104,7 @@ class xml_xfcepanel(xml_xfce): return True def _join(self, xmlNewNode, xmlOldNode, flagRootNode=True, levelNumber=0): - """Объединение корневой ноды профиля и корненвой ноды файла""" + """Объединение корневой ноды профиля и корневой ноды файла""" xmlNode = xmlNewNode childNodes = xmlNode.childNodes nextOldNode = xmlOldNode @@ -6329,3 +6330,239 @@ class dhcp(bind): """Объединяем конфигурации""" if isinstance(dhcpObj, dhcp): self.docObj.joinDoc(dhcpObj.doc) + + +class xml_gconf(xml_xfce): + """Класс для объединения gconf-xml файлов""" + # root нода + rootNode = False + # body нода + bodyNode = False + # Документ + doc = False + # Текст профиля + text = "" + # Текущее время в секундах + currentTime = "" + # Комментарий + _comment = ("") + # поддерживаемые аттрибуты тега entry. Пример + supportEntryTypes = ("int", "bool", "float", "string", "list") + + def __init__(self, text): + self.text = text + # Создаем пустой объект + self.docObj = type("_empty_class", (object,), {})() + # Названия аттрибутов для пустого объекта + emptyMethods = ["getNodeBody","removeComment","insertBRtoBody", + "insertBeforeSepAreas"] + # Добавляем необходимые аттрибуты пустому объекту + for method in emptyMethods: + setattr(self.docObj, method, self.emptyMethod) + # Пустой метод (не нужно имя файла для корневой ноды) + setattr(self, "setNameBodyNode", self.emptyMethod) + # Создаем XML документ + self.doc = self.textToXML() + + def getCurrentTime(self): + """Получение текущего времени в секундах""" + return str(int(time.time())) + + def textToXML(self): + """Создание из текста XML документа + Храним xml в своем формате + """ + if not self.text.strip(): + self.text = '''''' + try: + self.doc = xml.dom.minidom.parseString(self.text) + except: + self.setError(_("Can not text profile is XML")) + return False + self.rootNode = self.doc.documentElement + self.bodyNode = self.rootNode + return self.doc + + def cmpListsNodesEntry(self, listXmlA, listXmlB): + """Сравнение содержимого двух списков XML нод""" + getTextsNodes = lambda y: map(lambda x:\ + x.toxml().replace(" ","").replace("\t","").replace("\n",""), + map(lambda x: x.removeAttribute("mtime") or x, + map(lambda x: x.cloneNode(True), + filter(lambda x: x.nodeType==x.ELEMENT_NODE, y)))) + if set(getTextsNodes(listXmlA))==set(getTextsNodes(listXmlB)): + return True + return False + + def _join(self, xmlNewNode, xmlOldNode, flagRootNode=True, levelNumber=0): + """Объединение корневой ноды профиля и корневой ноды файла""" + if levelNumber>1: + return True + xmlNode = xmlNewNode + childNodes = xmlNode.childNodes + nextOldNode = xmlOldNode + flagError = False + if xmlNode.nodeType == xmlNode.ELEMENT_NODE: + n = xmlNode + tagName = n.tagName + nAction = u'' + nName = u'' + nType = u'' + nValue = u'' + attrName = '' + attrType = '' + if flagRootNode: + if not tagName == "gconf": + self.setError(_("The text is not a valid gconf-XML format \ +(not found '...')")) + return False + else: + if not tagName == "entry": + self.setError(_("The text is not a valid gconf-XML format \ +(found '<%s>..'")%(tagName,tagName)) + return False + if not n.hasAttribute("name"): + self.setError(_('Not found arrtibute "name" in tag entry')) + return False + if not n.hasAttribute("type"): + self.setError(_('Not found arrtibute "type" in tag entry')) + return False + nName = n.getAttribute("name") + attrName = u"attribute::name='%s'"%nName + nType = n.getAttribute("type") + # Проверка правильности аттрибута type + if not nType in self.supportEntryTypes: + self.setError(\ + _('Incorrect arrtibute "type" - ')%nType) + return False + attrType = u"attribute::type='%s'"%nType + if n.hasAttribute("value"): + nValue = n.getAttribute("value") + if n.hasAttribute("action"): + nAction = n.getAttribute("action") + if not nAction in ("join","replace","drop"): + textError = _('''In the text, XML profile, look \ +for a reserved attribute 'action' with the incorrect value.\n\ +Valid values attribute 'action': \ +(action="join", action="replace", action="drop")''') + self.setError(textError) + return False + if xmlOldNode.parentNode: + findStr = u"child::%s"%tagName + strAttr = [attrName, attrType] + findAttr = filter(lambda x: x, strAttr) + findAttrStr = '' + if findAttr: + strAttr = u' and '.join(findAttr) + findAttrStr = "[%s]"%strAttr + findPath = u"child::%s%s"%(tagName,findAttrStr) + # Рабочая нода + if flagRootNode: + workNode = xmlOldNode.parentNode + else: + workNode = xmlOldNode + oldNodes = xpath.Evaluate(findPath, workNode) + # Новая нода список + flagArray = False + if nType == "list": + flagArray = True + flagDrop = False + flagJoin = True + flagReplace = False + if nType=="string" or nAction=="replace": + flagJoin = False + flagReplace = True + elif nAction == "drop": + flagJoin = False + flagDrop = True + if flagRootNode: + textError = _('Incorrect action="drop" in root node') + self.setError(textError) + return False + if oldNodes: + if len(oldNodes)>1: + textError = _("The uncertainty in this profile are \ +the same nodes at one level") + self.setError(textError) + return False + nextOldNode = oldNodes[0] + # Замещаем ноду в случае массива + if flagArray and not flagDrop: + replaceXmlNode = xmlNode.cloneNode(True) + # Сравнение содержимого нод + if not self.cmpListsNodesEntry([replaceXmlNode], + [nextOldNode]): + replaceXmlNode.setAttribute("mtime", + self.currentTime) + if nAction: + replaceXmlNode.removeAttribute("action") + workNode.replaceChild(replaceXmlNode, + nextOldNode) + flagJoin = False + flagReplace = False + childNodes = False + # Объединение нод + if flagJoin: + if nextOldNode.hasAttribute("value"): + oValue = nextOldNode.getAttribute("value") + if nValue != oValue: + nextOldNode.setAttribute("mtime", + self.currentTime) + nextOldNode.setAttribute("value",nValue) + # Замещение ноды + elif flagReplace: + replaceXmlNode = xmlNode.cloneNode(True) + # Сравнение содержимого нод + if not self.cmpListsNodesEntry([replaceXmlNode], + [nextOldNode]): + replaceXmlNode.setAttribute("mtime", + self.currentTime) + if not\ + self._removeDropNodesAndAttrAction(\ + replaceXmlNode): + return False + workNode.replaceChild(replaceXmlNode, + nextOldNode) + childNodes = False + # Удаление ноды + elif flagDrop: + workNode.removeChild(nextOldNode) + childNodes = False + else: + # Добавление ноды + childNodes = False + if not flagDrop: + appendXmlNode = xmlNode.cloneNode(True) + appendXmlNode.setAttribute("mtime", self.currentTime) + if not\ + self._removeDropNodesAndAttrAction(appendXmlNode): + return False + workNode.appendChild(appendXmlNode) + if childNodes: + for node in childNodes: + levelNumber +=1 + if not self._join(node, nextOldNode, False, levelNumber): + flagError = True + break + levelNumber -= 1 + if flagError: + return False + return True + + def join(self, xml_gconfObj): + """Объединяем конфигурации""" + # Получаем текущее время + self.currentTime = self.getCurrentTime() + if isinstance(xml_gconfObj, xml_gconf): + try: + self.joinDoc(xml_gconfObj.doc) + except: + self.setError(_("Can not join profile")) + return False + return True + + def getConfig(self): + """Получение текстового файла из XML документа""" + data = self.doc.toprettyxml().split("\n") + data = filter(lambda x: x.strip(), data) + return "\n".join(data).replace("\t"," ")