head 1.14; access; symbols old2:1.5.2.2 old:1.5.0.2 iport_old:1.7.0.2 testing1:1.3 stable_1:1.2.0.2 working:1.3 v20030901:1.2; locks; strict; comment @# @; 1.14 date 2005.07.17.17.43.51; author snake; state Exp; branches; next 1.13; 1.13 date 2004.12.15.11.34.55; author snake; state Exp; branches; next 1.12; 1.12 date 2004.06.25.12.11.36; author snake; state Exp; branches; next 1.11; 1.11 date 2004.06.03.12.56.58; author snake; state Exp; branches; next 1.10; 1.10 date 2004.03.15.10.10.03; author snake; state Exp; branches; next 1.9; 1.9 date 2004.03.11.14.54.09; author snake; state Exp; branches; next 1.8; 1.8 date 2004.03.11.06.02.40; author snake; state Exp; branches; next 1.7; 1.7 date 2004.01.26.10.17.38; author snake; state Exp; branches; next 1.6; 1.6 date 2003.12.03.10.37.30; author cvsuser; state Exp; branches; next 1.5; 1.5 date 2003.11.17.13.48.55; author cvsuser; state Exp; branches 1.5.2.1; next 1.4; 1.4 date 2003.11.17.07.26.57; author cvsuser; state Exp; branches; next 1.3; 1.3 date 2003.11.04.13.09.27; author cvsuser; state Exp; branches; next 1.2; 1.2 date 2003.08.25.07.34.09; author webmaster; state Exp; branches; next 1.1; 1.1 date 2003.08.23.07.47.28; author snake; state Exp; branches; next ; 1.5.2.1 date 2005.07.17.17.43.07; author snake; state Exp; branches; next 1.5.2.2; 1.5.2.2 date 2005.07.17.17.43.16; author snake; state Exp; branches; next ; desc @@ 1.14 log @test check in 3 @ text @## simplexml.py based on Mattew Allum's xmlstream.py ## ## Copyright (C) 2003 Alexey "Snake" Nezhdanov ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2, or (at your option) ## any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. # $Id: simplexml.py,v 1.13 2004/12/15 11:34:55 snake Exp $ import xml.parsers.expat def XMLescape(txt): "Escape XML entities" txt = txt.replace("&", "&") txt = txt.replace("<", "<") txt = txt.replace(">", ">") return txt def XMLunescape(txt): "Unescape XML entities" txt = txt.replace(">", ">") txt = txt.replace("<", "<") txt = txt.replace("&", "&") return txt ENCODING='utf-8' def ustr(what): if type(what) == type(u''): return what try: r=what.__str__() except AttributeError: r=str(what) if type(r)<>type(u''): return unicode(r,ENCODING) return r class Node: def __init__(self, tag=None, attrs={}, payload=[], parent=None, node=None): if node: if type(node)<>type(self): node=NodeBuilder(node).getDom() self.name,self.namespace,self.attrs,self.data,self.kids,self.parent = node.name,node.namespace,node.attrs,node.data,node.kids,node.parent else: self.name,self.namespace,self.attrs,self.data,self.kids,self.parent = 'tag','',{},[],[],None if tag: self.namespace, self.name = (['']+str(tag).split())[-2:] if parent: self.parent = parent if self.parent and not self.namespace: self.namespace=self.parent.namespace for attr in attrs.keys(): self.attrs[attr]=ustr(attrs[attr]) if type(payload) in (type(''),type(u'')): payload=[payload] for i in payload: if type(i)==type(self): self.addChild(node=i) else: self.data.append(ustr(i)) def __str__(self,parent=None,fancy=0): s = (fancy-1) * 2 * ' ' + "<" + self.name if self.namespace: if parent and parent.namespace!=self.namespace: s = s + " xmlns='%s'"%self.namespace for key in self.attrs.keys(): val = self.attrs[key] s = s + " %s='%s'" % ( key, XMLescape(val) ) s = s + ">" cnt = 0 if self.kids: if fancy: s = s + "\n" for a in self.kids: if not fancy and (len(self.data)-1)>=cnt: s=s+XMLescape(self.data[cnt]) elif (len(self.data)-1)>=cnt: s=s+XMLescape(self.data[cnt].strip()) if fancy: s = s + a.__str__(self,fancy=fancy+1) else: s = s + a.__str__(self) cnt=cnt+1 if not fancy and (len(self.data)-1) >= cnt: s = s + XMLescape(self.data[cnt]) elif (len(self.data)-1) >= cnt: s = s + XMLescape(self.data[cnt].strip()) if not self.kids and s[-1:]=='>': s=s[:-1]+' />' if fancy: s = s + "\n" else: if fancy and not self.data: s = s + (fancy-1) * 2 * ' ' s = s + "" if fancy: s = s + "\n" return s def addChild(self, name=None, attrs={}, payload=[], namespace=None, node=None): if namespace: name=namespace+' '+name if node: newnode=node node.parent = self else: newnode=Node(tag=name, parent=self, attrs=attrs, payload=payload) self.kids.append(newnode) return newnode def addData(self, data): self.data.append(ustr(data)) def clearData(self): self.data=[] def delAttr(self, key): del self.attrs[key] def delChild(self, node, attrs={}): if type(node)<>type(self): node=self.getTag(node,attrs) self.kids.remove(node) return node def getAttrs(self): return self.attrs def getAttr(self, key): try: return str(self.attrs[key]) except: return None def getChildren(self): return self.kids def getData(self): try: return str(''.join(self.data)) except UnicodeError: return ''.join(self.data) def getName(self): return self.name def getNamespace(self): return self.namespace def getParent(self): return self.parent def getPayload(self): return self.kids def getTag(self, name, attrs={}, namespace=None): return self.getTags(name, attrs, namespace, one=1) def getTagAttr(self,tag,attr): try: return self.getTag(tag).attrs[attr] except: return None def getTagData(self,tag, attrs={}): try: return self.getTag(tag,attrs).getData() except: return None def getTags(self, name, attrs={}, namespace=None, one=0): nodes=[] for node in self.kids: if namespace and namespace<>node.getNamespace(): continue if node.getName() == name: for key in attrs.keys(): if not node.attrs.has_key(key) or node.attrs[key]<>attrs[key]: break else: nodes.append(node) if one and nodes: return nodes[0] if not one: return nodes def setAttr(self, key, val): self.attrs[key]=ustr(val) def setData(self, data): self.data=[ustr(data)] def setName(self,val): self.name = val def setNamespace(self, namespace): self.namespace=namespace def setParent(self, node): self.parent = node def setPayload(self,payload,add=0): if type(payload) in (type(''),type(u'')): payload=[payload] if add: self.kids+=payload else: self.kids=payload def setTag(self, name, attrs={}, namespace=None): node=self.getTags(name, attrs, namespace=namespace, one=1) if node: return node else: return self.addChild(name, attrs, namespace=namespace) def setTagAttr(self,tag,attr,val): try: self.getTag(tag).attrs[attr]=ustr(val) except: self.addChild(tag,attrs={attr:ustr(val)}) def setTagData(self,tag,val,attrs={}): try: self.getTag(tag,attrs).setData(ustr(val)) except: self.addChild(tag,attrs,payload=[ustr(val)]) def has_attr(self,key): return self.attrs.has_key(key) DBG_NODEBUILDER = 'nodebuilder' class NodeBuilder: def __init__(self,data=None): self.DEBUG(DBG_NODEBUILDER, "Preparing to handle incoming XML stream.", 'start') self._parser = xml.parsers.expat.ParserCreate(namespace_separator=' ') self._parser.StartElementHandler = self.starttag self._parser.EndElementHandler = self.endtag self._parser.CharacterDataHandler = self.handle_data self.Parse = self._parser.Parse self.__depth = 0 self._dispatch_depth = 1 self._document_attrs = None if data: self._parser.Parse(data,1) def starttag(self, tag, attrs): """XML Parser callback""" self.__depth += 1 self.DEBUG(DBG_NODEBUILDER, "DEPTH -> %i , tag -> %s, attrs -> %s" % (self.__depth, tag, `attrs`), 'down') if self.__depth == self._dispatch_depth: self._mini_dom = Node(tag=tag, attrs=attrs) self._ptr = self._mini_dom elif self.__depth > self._dispatch_depth: self._ptr.kids.append(Node(tag=tag,parent=self._ptr,attrs=attrs)) self._ptr = self._ptr.kids[-1] if self.__depth == 1: self._document_attrs = attrs self.last_is_data = 0 def endtag(self, tag ): """XML Parser callback""" self.DEBUG(DBG_NODEBUILDER, "DEPTH -> %i , tag -> %s" % (self.__depth, tag), 'up') if self.__depth == self._dispatch_depth: self.dispatch(self._mini_dom) elif self.__depth > self._dispatch_depth: self._ptr = self._ptr.parent else: self.DEBUG(DBG_NODEBUILDER, "Got higher than dispatch level. Stream terminated?", 'stop') self.__depth -= 1 self.last_is_data = 0 def handle_data(self, data): """XML Parser callback""" self.DEBUG(DBG_NODEBUILDER, data, 'data') if self.last_is_data: self._ptr.data[-1] += data else: self._ptr.data.append(data) self.last_is_data = 1 def DEBUG(self, level, text, comment=None): pass def getDom(self): return self._mini_dom def dispatch(self,stanza): pass def XML2Node(xml): return NodeBuilder(xml).getDom() @ 1.13 log @argument 'attrs' added to getTagData @ text @d15 1 a15 1 # $Id: simplexml.py,v 1.12 2004/06/25 12:11:36 snake Exp $ a151 2 """builds a 'minidom' from data parsed to it. Primarily for insertXML method of Node""" @ 1.12 log @Добавлен метод Node.has_attr @ text @d15 1 a15 1 # $Id: simplexml.py,v 1.11 2004/06/03 12:56:58 snake Exp $ d116 2 a117 2 def getTagData(self,tag): try: return self.getTag(tag).getData() @ 1.11 log @Пофиксена ошибка - addChild не ставил дитю родителя. @ text @d15 1 a15 1 # $Id: simplexml.py,v 1.10 2004/03/15 10:10:03 snake Exp $ d148 1 @ 1.10 log @Добавлены функции установки/смены пароля, смены email. @ text @d15 1 a15 1 # $Id: simplexml.py,v 1.9 2004/03/11 14:54:09 snake Exp $ d87 3 a89 1 if node: newnode=node @ 1.9 log @getData по-возможности возвращает не-юникодную стоку @ text @d15 1 a15 1 # $Id: simplexml.py,v 1.8 2004/03/11 06:02:40 snake Exp $ d48 1 a48 1 if tag: self.namespace, self.name = (['']+tag.split())[-2:] d100 1 a100 1 try: return self.attrs[key] @ 1.8 log @Библиотека синхронизирована с версией апстрима. @ text @d15 1 a15 1 # $Id: simplexml.py,v 1.8 2004/03/11 05:49:50 snakeru Exp $ d103 3 a105 1 def getData(self): return ''.join(self.data) @ 1.7 log @Добавлены комментарии отслеживающие ревижны. @ text @d1 17 a17 21 # -*- coding: koi8-r -*- # $Id: test_client.py,v 1.11 2003/11/08 06:37:36 snakeru Exp $ import re,xml.parsers.expat def ustr(what, encoding='koi8-r'): """ If sending object is already a unicode str, just return it, otherwise convert it using encoding """ if type(what) == type(u''): r = what else: try: r = what.__str__() except AttributeError, value: # inner __str__ is missing r = str(what) # make sure __str__() didnt return a unicode if type(r) <> type(u''): r = unicode(r,encoding,'replace') return r d33 8 d42 17 a58 102 """A simple XML DOM like class""" def __init__(self, tag=u'', parent=None, attrs=None ): bits = ustr(tag).split() if len(bits) == 1: self.name = ustr(tag) self.namespace = u'' else: self.namespace, self.name = bits if attrs is None: self.attrs = {} else: self.attrs = attrs self.data = [] self.kids = [] self.parent = parent def setParent(self, node): "Set the nodes parent node." self.parent = node def getParent(self): "return the nodes parent node." return self.parent def getName(self): "Set the nodes tag name." return self.name def setName(self,val): "Set the nodes tag name." self.name = ustr(val) def putAttr(self, key, val): "Add a name/value attribute to the node." self.attrs[key] = ustr(val) def getAttr(self, key): "Get a value for the nodes named attribute." try: return self.attrs[key] except: return None def putData(self, data): "Set the nodes textual data" self.data.append(ustr(data)) def insertData(self, data): "Set the nodes textual data" self.data.append(ustr(data)) def getData(self): "Return the nodes textual data" return ''.join(self.data) def getDataAsParts(self): "Return the node data as an array" return self.data def getNamespace(self): "Returns the nodes namespace." return self.namespace def setNamespace(self, namespace): "Set the nodes namespace." self.namespace = ustr(namespace) def insertTag(self, name, attrs=None): """ Add a child tag of name 'name' to the node. Returns the newly created node. """ newnode = Node(tag=name, parent=self, attrs=attrs) self.kids.append(newnode) return newnode def insertNode(self, node): "Add a child node to the node" self.kids.append(node) return node def insertNodes(self, nodes): "Add a child nodes to the node" for node in nodes: self.kids.append(node) def insertXML(self, xml_str): "Add raw xml as a child of the node" newnode = NodeBuilder(ustr(xml_str)).getDom() self.kids.append(newnode) return newnode def __str__(self): return self._xmlnode2str() def getXML(self): return self._xmlnode2str() def _xmlnode2str(self, parent=None, indent=u''): """Returns an xml ( string ) representation of the node and it children""" s = indent + "<" + self.name d60 2 a61 2 if parent and parent.namespace != self.namespace: s = s + " xmlns = '%s' " % self.namespace d63 2 a64 2 val = ustr(self.attrs[key]) s = s + u" %s='%s'" % ( key, XMLescape(val) ) d66 1 a66 1 cnt = 0 d68 1 a68 1 s+='\n' d70 4 a73 2 if (len(self.data)-1) >= cnt: s += ustr(XMLescape(self.data[cnt])) s = s + a._xmlnode2str(parent=self, indent=indent+' ') d75 5 a79 5 if (len(self.data)-1) >= cnt: s += ustr(XMLescape(self.data[cnt])) if self.kids: s+=indent if s[-1:]=='>': s=s[:-1]+'/>\n' d81 3 a83 1 s = s + "\n" d85 31 a115 10 def getTag(self, name, id=None): """Returns a child node with tag name. Returns None if not found.""" for node in self.kids: if node.getName() == name and (not id or node.getAttr('id')==id): return node def getTags(self, name, id=None): """Like getTag but returns a list with matching child nodes""" d118 26 a143 7 if node.getName() == name and (not id or node.getAttr('id')==id): nodes.append(node) return nodes def getChildren(self): """Returns a nodes children""" return self.kids d145 1 d149 2 a150 1 def __init__(self,data): d152 2 a153 2 self._parser.StartElementHandler = self.unknown_starttag self._parser.EndElementHandler = self.unknown_endtag d155 1 d158 2 a159 4 self.__done = 0 #needed ? self.__space_regex = re.compile('^\s+$') self._parser.Parse(data,1) d161 7 a167 3 def unknown_starttag(self, tag, attrs): self.__depth = self.__depth + 1 if self.__depth == 1: d170 2 a171 4 elif self.__depth > 1: self._ptr.kids.append(Node(tag =tag, parent=self._ptr, attrs =attrs )) d173 3 a175 2 else: ## fix this .... pass d177 4 a180 3 def unknown_endtag(self, tag ): self.__depth = self.__depth - 1 if self.__depth == 0: d182 1 a182 1 elif self.__depth > 0: d185 3 a187 1 pass d190 5 a194 1 if not self.__space_regex.match(data): ## check its not all blank d196 1 d198 3 a200 2 def dispatch(self,dom): self.__done = 1 d202 1 a202 2 def getDom(self): return self._mini_dom @ 1.6 log @Добавлен метод insertNodes. @ text @d2 1 @ 1.5 log @Функционал getTags распространён на getTag @ text @d118 5 @ 1.5.2.1 log @test checkin @ text @d131 2 @ 1.5.2.2 log @test checkin 2 @ text @d119 1 @ 1.4 log @Выборка тэгов теперь может производиться с указанием атрибута. @ text @d157 1 a157 1 def getTag(self, name): d161 1 a161 1 if node.getName() == name: a162 1 return None d168 2 a169 3 if node.getName() == name: if not id or id==node.getAttr('id'): nodes.append(node) @ 1.3 log @Добавлена строка -*- coding -*- @ text @d165 1 a165 1 def getTags(self, name): d170 2 a171 1 nodes.append(node) @ 1.2 log @Убраны инденты. @ text @d1 1 d146 1 a146 1 s = s + a._xmlnode2str(parent=self, indent=indent+'') @ 1.1 log @Initial version. @ text @d145 1 a145 1 s = s + a._xmlnode2str(parent=self, indent=indent+' ') @