1 """A quick DOM implementation.
3 Python's xml.dom is very slow. The xml.sax module is also slow (as it imports urllib2).
4 This is our light-weight version.
7 # Copyright (C) 2009, Thomas Leonard
8 # See the README file for details, or visit http://0install.net.
10 from zeroinstall
import _
11 from xml
.parsers
import expat
13 class Element(object):
15 @ivar uri: the element's namespace
17 @ivar name: the element's localName
19 @ivar attrs: the element's attributes (key is in the form [namespace " "] localName
20 @type attrs: {str: str}
21 @ivar childNodes: children
22 @type childNodes: [L{Element}]
23 @ivar content: the text content
25 __slots__
= ['uri', 'name', 'attrs', 'childNodes', 'content']
26 def __init__(self
, uri
, name
, attrs
):
29 self
.attrs
= attrs
.copy()
33 attrs
= [n
+ '=' + self
.attrs
[n
] for n
in self
.attrs
]
34 start
= '<{%s}%s %s' % (self
.uri
, self
.name
, ' '.join(attrs
))
36 return start
+ '>' + '\n'.join(map(str, self
.childNodes
)) + ('</%s>' % (self
.name
))
38 return start
+ '>' + self
.content
+ ('</%s>' % (self
.name
))
42 def getAttribute(self
, name
):
43 return self
.attrs
.get(name
, None)
46 """SAXHandler that builds a tree of L{Element}s"""
50 def startElementNS(self
, fullname
, attrs
):
51 split
= fullname
.split(' ', 1)
53 self
.stack
.append(Element(split
[0], split
[1], attrs
))
55 self
.stack
.append(Element(None, fullname
, attrs
))
58 def characters(self
, data
):
61 def endElementNS(self
, name
):
62 contents
= self
.contents
.strip()
63 self
.stack
[-1].content
= contents
65 new
= self
.stack
.pop()
67 self
.stack
[-1].childNodes
.append(new
)
72 """Parse an XML stream into a tree of L{Element}s.
73 @param source: data to parse
77 handler
= QSAXhandler()
78 parser
= expat
.ParserCreate(namespace_separator
= ' ')
80 parser
.StartElementHandler
= handler
.startElementNS
81 parser
.EndElementHandler
= handler
.endElementNS
82 parser
.CharacterDataHandler
= handler
.characters
84 parser
.ParseFile(source
)