author | Mikael Berthe <mikael@lilotux.net> |
Tue, 01 May 2007 12:26:35 +0200 | |
changeset 0 | 93b25987d3e5 |
permissions | -rw-r--r-- |
0
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
1 |
## simplexml.py based on Mattew Allum's xmlstream.py |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
2 |
## |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
3 |
## Copyright (C) 2003-2005 Alexey "Snake" Nezhdanov |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
4 |
## |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
5 |
## This program is free software; you can redistribute it and/or modify |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
6 |
## it under the terms of the GNU General Public License as published by |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
7 |
## the Free Software Foundation; either version 2, or (at your option) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
8 |
## any later version. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
9 |
## |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
10 |
## This program is distributed in the hope that it will be useful, |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
11 |
## but WITHOUT ANY WARRANTY; without even the implied warranty of |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
12 |
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
13 |
## GNU General Public License for more details. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
14 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
15 |
# $Id: simplexml.py,v 1.30 2006/06/03 12:22:34 normanr Exp $ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
16 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
17 |
"""Simplexml module provides xmpppy library with all needed tools to handle XML nodes and XML streams. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
18 |
I'm personally using it in many other separate projects. It is designed to be as standalone as possible.""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
19 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
20 |
import xml.parsers.expat |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
21 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
22 |
def XMLescape(txt): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
23 |
"""Returns provided string with symbols & < > " replaced by their respective XML entities.""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
24 |
return txt.replace("&", "&").replace("<", "<").replace(">", ">").replace('"', """) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
25 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
26 |
ENCODING='utf-8' |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
27 |
def ustr(what): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
28 |
"""Converts object "what" to unicode string using it's own __str__ method if accessible or unicode method otherwise.""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
29 |
if type(what) == type(u''): return what |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
30 |
try: r=what.__str__() |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
31 |
except AttributeError: r=str(what) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
32 |
if type(r)<>type(u''): return unicode(r,ENCODING) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
33 |
return r |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
34 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
35 |
class Node: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
36 |
""" Node class describes syntax of separate XML Node. It have a constructor that permits node creation |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
37 |
from set of "namespace name", attributes and payload of text strings and other nodes. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
38 |
It does not natively support building node from text string and uses NodeBuilder class for that purpose. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
39 |
After creation node can be mangled in many ways so it can be completely changed. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
40 |
Also node can be serialised into string in one of two modes: default (where the textual representation |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
41 |
of node describes it exactly) and "fancy" - with whitespace added to make indentation and thus make |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
42 |
result more readable by human. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
43 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
44 |
Node class have attribute FORCE_NODE_RECREATION that is defaults to False thus enabling fast node |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
45 |
replication from the some other node. The drawback of the fast way is that new node shares some |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
46 |
info with the "original" node that is changing the one node may influence the other. Though it is |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
47 |
rarely needed (in xmpppy it is never needed at all since I'm usually never using original node after |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
48 |
replication (and using replication only to move upwards on the classes tree). |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
49 |
""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
50 |
FORCE_NODE_RECREATION=0 |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
51 |
def __init__(self, tag=None, attrs={}, payload=[], parent=None, node=None): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
52 |
""" Takes "tag" argument as the name of node (prepended by namespace, if needed and separated from it |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
53 |
by a space), attrs dictionary as the set of arguments, payload list as the set of textual strings |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
54 |
and child nodes that this node carries within itself and "parent" argument that is another node |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
55 |
that this one will be the child of. Also the __init__ can be provided with "node" argument that is |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
56 |
either a text string containing exactly one node or another Node instance to begin with. If both |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
57 |
"node" and other arguments is provided then the node initially created as replica of "node" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
58 |
provided and then modified to be compliant with other arguments.""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
59 |
if node: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
60 |
if self.FORCE_NODE_RECREATION and type(node)==type(self): node=str(node) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
61 |
if type(node)<>type(self): node=NodeBuilder(node,self) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
62 |
else: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
63 |
self.name,self.namespace,self.attrs,self.data,self.kids,self.parent = node.name,node.namespace,{},[],[],node.parent |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
64 |
for key in node.attrs.keys(): self.attrs[key]=node.attrs[key] |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
65 |
for data in node.data: self.data.append(data) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
66 |
for kid in node.kids: self.kids.append(kid) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
67 |
else: self.name,self.namespace,self.attrs,self.data,self.kids,self.parent = 'tag','',{},[],[],None |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
68 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
69 |
if tag: self.namespace, self.name = ([self.namespace]+tag.split())[-2:] |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
70 |
if parent: self.parent = parent |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
71 |
if self.parent and not self.namespace: self.namespace=self.parent.namespace |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
72 |
for attr in attrs.keys(): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
73 |
self.attrs[attr]=attrs[attr] |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
74 |
if type(payload) in (type(''),type(u'')): payload=[payload] |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
75 |
for i in payload: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
76 |
if type(i)==type(self): self.addChild(node=i) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
77 |
else: self.data.append(ustr(i)) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
78 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
79 |
def __str__(self,fancy=0): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
80 |
""" Method used to dump node into textual representation. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
81 |
if "fancy" argument is set to True produces indented output for readability.""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
82 |
s = (fancy-1) * 2 * ' ' + "<" + self.name |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
83 |
if self.namespace: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
84 |
if not self.parent or self.parent.namespace!=self.namespace: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
85 |
s = s + ' xmlns="%s"'%self.namespace |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
86 |
for key in self.attrs.keys(): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
87 |
val = ustr(self.attrs[key]) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
88 |
s = s + ' %s="%s"' % ( key, XMLescape(val) ) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
89 |
s = s + ">" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
90 |
cnt = 0 |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
91 |
if self.kids: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
92 |
if fancy: s = s + "\n" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
93 |
for a in self.kids: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
94 |
if not fancy and (len(self.data)-1)>=cnt: s=s+XMLescape(self.data[cnt]) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
95 |
elif (len(self.data)-1)>=cnt: s=s+XMLescape(self.data[cnt].strip()) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
96 |
s = s + a.__str__(fancy and fancy+1) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
97 |
cnt=cnt+1 |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
98 |
if not fancy and (len(self.data)-1) >= cnt: s = s + XMLescape(self.data[cnt]) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
99 |
elif (len(self.data)-1) >= cnt: s = s + XMLescape(self.data[cnt].strip()) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
100 |
if not self.kids and s[-1:]=='>': |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
101 |
s=s[:-1]+' />' |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
102 |
if fancy: s = s + "\n" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
103 |
else: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
104 |
if fancy and not self.data: s = s + (fancy-1) * 2 * ' ' |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
105 |
s = s + "</" + self.name + ">" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
106 |
if fancy: s = s + "\n" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
107 |
return s |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
108 |
def getCDATA(self): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
109 |
""" Serialise node, dropping all tags and leaving CDATA intact. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
110 |
That is effectively kills all formatiing, leaving only text were contained in XML. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
111 |
""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
112 |
s ="" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
113 |
cnt = 0 |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
114 |
if self.kids: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
115 |
for a in self.kids: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
116 |
s=s+self.data[cnt] |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
117 |
s = s + mystr(a) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
118 |
cnt=cnt+1 |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
119 |
if (len(self.data)-1) >= cnt: s = s + self.data[cnt] |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
120 |
return s |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
121 |
def addChild(self, name=None, attrs={}, payload=[], namespace=None, node=None): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
122 |
""" If "node" argument is provided, adds it as child node. Else creates new node from |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
123 |
the other arguments' values and adds it as well.""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
124 |
if attrs.has_key('xmlns'): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
125 |
raise AttributeError("Use namespace=x instead of attrs={'xmlns':x}") |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
126 |
if namespace: name=namespace+' '+name |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
127 |
if node: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
128 |
newnode=node |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
129 |
node.parent = self |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
130 |
else: newnode=Node(tag=name, parent=self, attrs=attrs, payload=payload) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
131 |
self.kids.append(newnode) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
132 |
return newnode |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
133 |
def addData(self, data): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
134 |
""" Adds some CDATA to node. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
135 |
self.data.append(ustr(data)) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
136 |
def clearData(self): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
137 |
""" Removes all CDATA from the node. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
138 |
self.data=[] |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
139 |
def delAttr(self, key): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
140 |
""" Deletes an attribute "key" """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
141 |
del self.attrs[key] |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
142 |
def delChild(self, node, attrs={}): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
143 |
""" Deletes the "node" from the node's childs list, if "node" is an instance. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
144 |
Else deletes the first node that have specified name and (optionally) attributes. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
145 |
if type(node)<>type(self): node=self.getTag(node,attrs) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
146 |
self.kids.remove(node) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
147 |
return node |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
148 |
def getAttrs(self): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
149 |
""" Returns all node's attributes as dictionary. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
150 |
return self.attrs |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
151 |
def getAttr(self, key): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
152 |
""" Returns value of specified attribute. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
153 |
try: return self.attrs[key] |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
154 |
except: return None |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
155 |
def getChildren(self): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
156 |
""" Returns all node's child nodes as list. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
157 |
return self.kids |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
158 |
def getData(self): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
159 |
""" Returns all node CDATA as string (concatenated). """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
160 |
return ''.join(self.data) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
161 |
def getName(self): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
162 |
""" Returns the name of node """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
163 |
return self.name |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
164 |
def getNamespace(self): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
165 |
""" Returns the namespace of node """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
166 |
return self.namespace |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
167 |
def getParent(self): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
168 |
""" Returns the parent of node (if present). """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
169 |
return self.parent |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
170 |
def getPayload(self): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
171 |
""" Return the payload of node i.e. list of child nodes and CDATA entries. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
172 |
F.e. for "<node>text1<nodea/><nodeb/> text2</node>" will be returned list: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
173 |
['text1', <nodea instance>, <nodeb instance>, ' text2']. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
174 |
ret=[] |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
175 |
for i in range(len(self.kids)+len(self.data)+1): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
176 |
try: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
177 |
if self.data[i]: ret.append(self.data[i]) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
178 |
except IndexError: pass |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
179 |
try: ret.append(self.kids[i]) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
180 |
except IndexError: pass |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
181 |
return ret |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
182 |
def getTag(self, name, attrs={}, namespace=None): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
183 |
""" Filters all child nodes using specified arguments as filter. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
184 |
Returns the first found or None if not found. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
185 |
return self.getTags(name, attrs, namespace, one=1) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
186 |
def getTagAttr(self,tag,attr): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
187 |
""" Returns attribute value of the child with specified name (or None if no such attribute).""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
188 |
try: return self.getTag(tag).attrs[attr] |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
189 |
except: return None |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
190 |
def getTagData(self,tag): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
191 |
""" Returns cocatenated CDATA of the child with specified name.""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
192 |
try: return self.getTag(tag).getData() |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
193 |
except: return None |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
194 |
def getTags(self, name, attrs={}, namespace=None, one=0): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
195 |
""" Filters all child nodes using specified arguments as filter. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
196 |
Returns the list of nodes found. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
197 |
nodes=[] |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
198 |
for node in self.kids: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
199 |
if namespace and namespace<>node.getNamespace(): continue |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
200 |
if node.getName() == name: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
201 |
for key in attrs.keys(): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
202 |
if not node.attrs.has_key(key) or node.attrs[key]<>attrs[key]: break |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
203 |
else: nodes.append(node) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
204 |
if one and nodes: return nodes[0] |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
205 |
if not one: return nodes |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
206 |
def setAttr(self, key, val): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
207 |
""" Sets attribute "key" with the value "val". """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
208 |
self.attrs[key]=val |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
209 |
def setData(self, data): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
210 |
""" Sets node's CDATA to provided string. Resets all previous CDATA!""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
211 |
self.data=[ustr(data)] |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
212 |
def setName(self,val): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
213 |
""" Changes the node name. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
214 |
self.name = val |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
215 |
def setNamespace(self, namespace): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
216 |
""" Changes the node namespace. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
217 |
self.namespace=namespace |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
218 |
def setParent(self, node): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
219 |
""" Sets node's parent to "node". WARNING: do not checks if the parent already present |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
220 |
and not removes the node from the list of childs of previous parent. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
221 |
self.parent = node |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
222 |
def setPayload(self,payload,add=0): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
223 |
""" Sets node payload according to the list specified. WARNING: completely replaces all node's |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
224 |
previous content. If you wish just to add child or CDATA - use addData or addChild methods. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
225 |
if type(payload) in (type(''),type(u'')): payload=[payload] |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
226 |
if add: self.kids+=payload |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
227 |
else: self.kids=payload |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
228 |
def setTag(self, name, attrs={}, namespace=None): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
229 |
""" Same as getTag but if the node with specified namespace/attributes not found, creates such |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
230 |
node and returns it. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
231 |
node=self.getTags(name, attrs, namespace=namespace, one=1) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
232 |
if node: return node |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
233 |
else: return self.addChild(name, attrs, namespace=namespace) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
234 |
def setTagAttr(self,tag,attr,val): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
235 |
""" Creates new node (if not already present) with name "tag" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
236 |
and sets it's attribute "attr" to value "val". """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
237 |
try: self.getTag(tag).attrs[attr]=val |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
238 |
except: self.addChild(tag,attrs={attr:val}) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
239 |
def setTagData(self,tag,val,attrs={}): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
240 |
""" Creates new node (if not already present) with name "tag" and (optionally) attributes "attrs" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
241 |
and sets it's CDATA to string "val". """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
242 |
try: self.getTag(tag,attrs).setData(ustr(val)) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
243 |
except: self.addChild(tag,attrs,payload=[ustr(val)]) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
244 |
def has_attr(self,key): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
245 |
""" Checks if node have attribute "key".""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
246 |
return self.attrs.has_key(key) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
247 |
def __getitem__(self,item): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
248 |
""" Returns node's attribute "item" value. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
249 |
return self.getAttr(item) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
250 |
def __setitem__(self,item,val): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
251 |
""" Sets node's attribute "item" value. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
252 |
return self.setAttr(item,val) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
253 |
def __delitem__(self,item): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
254 |
""" Deletes node's attribute "item". """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
255 |
return self.delAttr(item,val) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
256 |
def __getattr__(self,attr): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
257 |
""" Reduce memory usage caused by T/NT classes - use memory only when needed. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
258 |
if attr=='T': |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
259 |
self.T=T(self) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
260 |
return self.T |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
261 |
if attr=='NT': |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
262 |
self.NT=NT(self) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
263 |
return self.NT |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
264 |
raise AttributeError |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
265 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
266 |
class T: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
267 |
""" Auxiliary class used to quick access to node's child nodes. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
268 |
def __init__(self,node): self.__dict__['node']=node |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
269 |
def __getattr__(self,attr): return self.node.getTag(attr) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
270 |
def __setattr__(self,attr,val): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
271 |
if isinstance(val,Node): Node.__init__(self.node.setTag(attr),node=val) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
272 |
else: return self.node.setTagData(attr,val) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
273 |
def __delattr__(self,attr): return self.node.delChild(attr) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
274 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
275 |
class NT(T): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
276 |
""" Auxiliary class used to quick create node's child nodes. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
277 |
def __getattr__(self,attr): return self.node.addChild(attr) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
278 |
def __setattr__(self,attr,val): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
279 |
if isinstance(val,Node): self.node.addChild(attr,node=val) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
280 |
else: return self.node.addChild(attr,payload=[val]) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
281 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
282 |
DBG_NODEBUILDER = 'nodebuilder' |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
283 |
class NodeBuilder: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
284 |
""" Builds a Node class minidom from data parsed to it. This class used for two purposes: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
285 |
1. Creation an XML Node from a textual representation. F.e. reading a config file. See an XML2Node method. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
286 |
2. Handling an incoming XML stream. This is done by mangling |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
287 |
the __dispatch_depth parameter and redefining the dispatch method. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
288 |
You do not need to use this class directly if you do not designing your own XML handler.""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
289 |
def __init__(self,data=None,initial_node=None): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
290 |
""" Takes two optional parameters: "data" and "initial_node". |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
291 |
By default class initialised with empty Node class instance. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
292 |
Though, if "initial_node" is provided it used as "starting point". |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
293 |
You can think about it as of "node upgrade". |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
294 |
"data" (if provided) feeded to parser immidiatedly after instance init. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
295 |
""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
296 |
self.DEBUG(DBG_NODEBUILDER, "Preparing to handle incoming XML stream.", 'start') |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
297 |
self._parser = xml.parsers.expat.ParserCreate(namespace_separator=' ') |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
298 |
self._parser.StartElementHandler = self.starttag |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
299 |
self._parser.EndElementHandler = self.endtag |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
300 |
self._parser.CharacterDataHandler = self.handle_data |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
301 |
self._parser.StartNamespaceDeclHandler = self.handle_namespace_start |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
302 |
self.Parse = self._parser.Parse |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
303 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
304 |
self.__depth = 0 |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
305 |
self._dispatch_depth = 1 |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
306 |
self._document_attrs = None |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
307 |
self._mini_dom=initial_node |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
308 |
self.last_is_data = 1 |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
309 |
self._ptr=None |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
310 |
self.namespaces={"http://www.w3.org/XML/1998/namespace":'xml:'} |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
311 |
self.xmlns="http://www.w3.org/XML/1998/namespace" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
312 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
313 |
if data: self._parser.Parse(data,1) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
314 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
315 |
def destroy(self): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
316 |
""" Method used to allow class instance to be garbage-collected. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
317 |
self._parser.StartElementHandler = None |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
318 |
self._parser.EndElementHandler = None |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
319 |
self._parser.CharacterDataHandler = None |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
320 |
self._parser.StartNamespaceDeclHandler = None |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
321 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
322 |
def starttag(self, tag, attrs): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
323 |
"""XML Parser callback. Used internally""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
324 |
attlist=attrs.keys() # |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
325 |
for attr in attlist: # FIXME: Crude hack. And it also slows down the whole library considerably. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
326 |
sp=attr.rfind(" ") # |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
327 |
if sp==-1: continue # |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
328 |
ns=attr[:sp] # |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
329 |
attrs[self.namespaces[ns]+attr[sp+1:]]=attrs[attr] |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
330 |
del attrs[attr] # |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
331 |
self.__depth += 1 |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
332 |
self.DEBUG(DBG_NODEBUILDER, "DEPTH -> %i , tag -> %s, attrs -> %s" % (self.__depth, tag, `attrs`), 'down') |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
333 |
if self.__depth == self._dispatch_depth: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
334 |
if not self._mini_dom : self._mini_dom = Node(tag=tag, attrs=attrs) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
335 |
else: Node.__init__(self._mini_dom,tag=tag, attrs=attrs) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
336 |
self._ptr = self._mini_dom |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
337 |
elif self.__depth > self._dispatch_depth: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
338 |
self._ptr.kids.append(Node(tag=tag,parent=self._ptr,attrs=attrs)) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
339 |
self._ptr = self._ptr.kids[-1] |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
340 |
if self.__depth == 1: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
341 |
self._document_attrs = attrs |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
342 |
ns, name = (['']+tag.split())[-2:] |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
343 |
self.stream_header_received(ns, name, attrs) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
344 |
if not self.last_is_data and self._ptr.parent: self._ptr.parent.data.append('') |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
345 |
self.last_is_data = 0 |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
346 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
347 |
def endtag(self, tag ): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
348 |
"""XML Parser callback. Used internally""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
349 |
self.DEBUG(DBG_NODEBUILDER, "DEPTH -> %i , tag -> %s" % (self.__depth, tag), 'up') |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
350 |
if self.__depth == self._dispatch_depth: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
351 |
self.dispatch(self._mini_dom) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
352 |
elif self.__depth > self._dispatch_depth: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
353 |
self._ptr = self._ptr.parent |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
354 |
else: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
355 |
self.DEBUG(DBG_NODEBUILDER, "Got higher than dispatch level. Stream terminated?", 'stop') |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
356 |
self.__depth -= 1 |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
357 |
self.last_is_data = 0 |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
358 |
if self.__depth == 0: self.stream_footer_received() |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
359 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
360 |
def handle_data(self, data): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
361 |
"""XML Parser callback. Used internally""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
362 |
self.DEBUG(DBG_NODEBUILDER, data, 'data') |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
363 |
if not self._ptr: return |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
364 |
if self.last_is_data: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
365 |
self._ptr.data[-1] += data |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
366 |
else: |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
367 |
self._ptr.data.append(data) |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
368 |
self.last_is_data = 1 |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
369 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
370 |
def handle_namespace_start(self, prefix, uri): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
371 |
"""XML Parser callback. Used internally""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
372 |
if prefix: self.namespaces[uri]=prefix+':' |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
373 |
else: self.xmlns=uri |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
374 |
def DEBUG(self, level, text, comment=None): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
375 |
""" Gets all NodeBuilder walking events. Can be used for debugging if redefined.""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
376 |
def getDom(self): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
377 |
""" Returns just built Node. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
378 |
return self._mini_dom |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
379 |
def dispatch(self,stanza): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
380 |
""" Gets called when the NodeBuilder reaches some level of depth on it's way up with the built |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
381 |
node as argument. Can be redefined to convert incoming XML stanzas to program events. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
382 |
def stream_header_received(self,ns,tag,attrs): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
383 |
""" Method called when stream just opened. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
384 |
def stream_footer_received(self): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
385 |
""" Method called when stream just closed. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
386 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
387 |
def XML2Node(xml): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
388 |
""" Converts supplied textual string into XML node. Handy f.e. for reading configuration file. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
389 |
Raises xml.parser.expat.parsererror if provided string is not well-formed XML. """ |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
390 |
return NodeBuilder(xml).getDom() |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
391 |
|
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
392 |
def BadXML2Node(xml): |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
393 |
""" Converts supplied textual string into XML node. Survives if xml data is cutted half way round. |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
394 |
I.e. "<html>some text <br>some more text". Will raise xml.parser.expat.parsererror on misplaced |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
395 |
tags though. F.e. "<b>some text <br>some more text</b>" will not work.""" |
93b25987d3e5
Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff
changeset
|
396 |
return NodeBuilder(xml).getDom() |