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.
calculate-utils-2.2-lib/pym/format/xml_xfce.py

266 lines
11 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#-*- coding: utf-8 -*-
# Copyright 2008-2010 Calculate Ltd. http://www.calculate-linux.org
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
from xml import xpath
import xml.dom.minidom
from cl_utils import _error
# Перевод cообщений модуля
from cl_lang import lang
tr = lang()
tr.setLocalDomain('cl_lib')
tr.setLanguage(sys.modules[__name__])
class xml_xfce(_error):
"""Класс для объединения xfce-xml файлов"""
# root нода
rootNode = False
# body нода
bodyNode = False
# Документ
doc = False
# Текст шаблона
text = ""
# Комментарий
_comment = ("<!--","-->")
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)
# Создаем XML документ
self.doc = self.textToXML()
def emptyMethod(self, *arg , **argv):
"""Пустой метод"""
return True
def setNameBodyNode(self, name):
"""Устанавливает название для корневой ноды документа"""
if not self.bodyNode:
return False
self.bodyNode.setAttribute("name", name)
return True
def textToXML(self):
"""Создание из текста XML документа
Храним xml в своем формате
"""
if not self.text.strip():
self.text = '''<?xml version="1.0" encoding="UTF-8"?>
<channel version="1.0">
</channel>'''
try:
self.doc = xml.dom.minidom.parseString(self.text)
except:
self.setError(_("Template text is not XML"))
return False
self.rootNode = self.doc.documentElement
self.bodyNode = self.rootNode
return self.doc
def join(self, xml_xfceObj):
"""Объединяем конфигурации"""
if isinstance(xml_xfceObj, xml_xfce):
try:
self.joinDoc(xml_xfceObj.doc)
except:
self.setError(_("Can not join template"))
return False
return True
def _removeDropNodesAndAttrAction(self, xmlNode):
"""Удаляет ноды с аттрибутом action='drop'
Также удаляет аттрибут action у всех нод
"""
flagError = False
childNodes = xmlNode.childNodes
if xmlNode.nodeType ==xmlNode.ELEMENT_NODE:
if xmlNode.hasAttribute("action"):
nAction = xmlNode.getAttribute("action")
if not nAction in ("join","replace","drop"):
textError = _('''In the text, XML template, 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
xmlNode.removeAttribute("action")
if nAction == "drop":
parentNode = xmlNode.parentNode
if parentNode:
parentNode.removeChild(xmlNode)
if childNodes:
for node in childNodes:
if not self._removeDropNodesAndAttrAction(node):
flagError = True
break
if flagError:
return False
return True
def postXML(self):
"""Последующая постобработка XML"""
# Удаляем теги action и удаляемые ноды
self._removeDropNodesAndAttrAction(self.bodyNode)
def _join(self, xmlNewNode, xmlOldNode, flagRootNode=True):
"""Объединение корневой ноды шаблона и корневой ноды файла"""
xmlNode = xmlNewNode
childNodes = xmlNode.childNodes
nextOldNode = xmlOldNode
flagError = False
if xmlNode.nodeType ==xmlNode.ELEMENT_NODE:
n = xmlNode
path = u''
nName = u''
nType = u''
nValue = u''
nAction = u''
attrName = ''
attrType = ''
path = n.tagName
if n.hasAttribute("name"):
nName = n.getAttribute("name")
attrName = u"attribute::name='%s'"%nName
if n.hasAttribute("type"):
nType = n.getAttribute("type")
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 template, 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:
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"%(path,findAttrStr)
# Рабочая нода
if flagRootNode:
workNode = xmlOldNode.parentNode
else:
workNode = xmlOldNode
oldNodes = xpath.Evaluate(findPath, workNode)
# Новая нода список
flagArray = False
if nType == "array":
flagArray = True
flagDrop = False
flagJoin = True
flagReplace = False
if 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 template 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 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("value",nValue)
# Замещение ноды
elif flagReplace:
replaceXmlNode = xmlNode.cloneNode(True)
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)
if not\
self._removeDropNodesAndAttrAction(appendXmlNode):
return False
workNode.appendChild(appendXmlNode)
if childNodes:
for node in childNodes:
if not self._join(node, nextOldNode, False):
flagError = True
break
if flagError:
return False
return True
def joinDoc(self, doc):
"""Объединение документа шаблона и документа файла"""
if not self.doc:
self.setError(_("Text file is not XML"))
return False
if not doc:
self.setError(_("Text file is not XML"))
return False
# Импортируем корневую ноду нового документа в текущий документ
#newImportBodyNode = self.doc.importNode(doc.documentElement, True)
# Объединение корневой ноды шаблона и корневой ноды файла
if not self._join(doc.documentElement, self.bodyNode):
return False
return True
def getConfig(self):
"""Получение текстового файла из XML документа"""
data = self.doc.toprettyxml(encoding='UTF-8').split("\n")
data = filter(lambda x: x.strip(), data)
return "\n".join(data).replace("\t"," ").decode("UTF-8")