On Jan 25, 4:32 am, "Fredrik Lundh" <fred...@python ware.comwrote:
"mukappa" wrote:
Is it possible to subclass cElementTree.XM LTreeBuilder?no , it's a factory function. if you need to extend it, you'll have to wrap it. but
I'm not sure I see the use case; what is it you're trying to do here?
</F>
I'm trying to parse xmpp stanzas coming in over a socket. Since
cElementTree is
more efficient, I would like to use it when available.
Here is what I have now:
import logging
from elementtree import ElementTree
class StanzaTreeBuild er(ElementTree. XMLTreeBuilder) :
"""Capture stanza elements (<streamchildre n) from parser events.
Private methods are lifted from the old
elementtree.XML TreeBuilder.Fan cyTreeBuilder
"""
def __init__(self, html=0):
"""Initiali ze state variables."""
ElementTree.XML TreeBuilder.__i nit__(self, html)
self._parser.St artNamespaceDec lHandler = self._start_ns
self._parser.En dNamespaceDeclH andler = self._end_ns
self.namespaces = []
self.level = 0
self.stanza = None
self.streamelem = None
def _start(self, tag, attrib_in):
elem = ElementTree.XML TreeBuilder._st art(self, tag, attrib_in)
self.start(elem )
def _start_list(sel f, tag, attrib_in):
elem = ElementTree.XML TreeBuilder._st art_list(self, tag,
attrib_in)
self.start(elem )
def _end(self, tag):
elem = ElementTree.XML TreeBuilder._en d(self, tag)
self.end(elem)
def _start_ns(self, prefix, value):
self.namespaces .insert(0, (prefix, value))
def _end_ns(self, prefix):
assert self.namespaces .pop(0)[0] == prefix, "implementa tion
confused"
def start(self, element):
"""Track nesting level (capture open <streamon first
call)."""
logging.debug(" start(%s): %s" %
(self.level, ElementTree.tos tring(element)) )
if self.streamelem is None:
assert element.tag == "http://etherx.jabber.o rg/streams"
self.streamelem = element
self.stanza = element
self.level += 1
def end(self, element):
"""Capture stanza when nesting level is 1."""
self.level -= 1
if self.level == 1:
self.stanza = element
self.streamelem .clear()
logging.debug(" end(%s): %s" %
(self.level, ElementTree.tos tring(element)) )
def stanzagen(socke t):
"""Yield open <stream ...on first call, then complete stanzas.
Caller needs 'id' from the opening <stream>, then he needs stanzas,
one per call. Works by parsing the socket one byte at a time, and
yielding complete stanza at earliest opportunity (or None if none
waiting), exits on EOF. Stanzas are returned as ElementTree
Elements
to give them a natural pythonic feel.
see
http://online.effbot.o rg/2004_12_01_arch ive.htm#element-generator"""
p = StanzaTreeBuild er()
data = None
while 1:
try:
data = socket.recv(1)
if not data:
logging.info("E OF from peer")
p.close()
break
p.feed(data)
if p.stanza is not None:
yield p.stanza
p.stanza = None
data = None
except:
if data is not None:
logging.error(" error reading: %s" % (data))
raise
else:
yield None