2014-07-21 19:01:46 -04:00
|
|
|
from __future__ import absolute_import, division, unicode_literals
|
|
|
|
|
2014-03-10 01:18:05 -04:00
|
|
|
from xml.dom.pulldom import START_ELEMENT, END_ELEMENT, \
|
|
|
|
COMMENT, IGNORABLE_WHITESPACE, CHARACTERS
|
|
|
|
|
2014-07-21 19:01:46 -04:00
|
|
|
from . import _base
|
|
|
|
|
|
|
|
from ..constants import voidElements
|
2014-03-10 01:18:05 -04:00
|
|
|
|
|
|
|
|
|
|
|
class TreeWalker(_base.TreeWalker):
|
|
|
|
def __iter__(self):
|
|
|
|
ignore_until = None
|
|
|
|
previous = None
|
|
|
|
for event in self.tree:
|
|
|
|
if previous is not None and \
|
2014-07-21 19:01:46 -04:00
|
|
|
(ignore_until is None or previous[1] is ignore_until):
|
2014-03-10 01:18:05 -04:00
|
|
|
if previous[1] is ignore_until:
|
|
|
|
ignore_until = None
|
|
|
|
for token in self.tokens(previous, event):
|
|
|
|
yield token
|
|
|
|
if token["type"] == "EmptyTag":
|
|
|
|
ignore_until = previous[1]
|
|
|
|
previous = event
|
|
|
|
if ignore_until is None or previous[1] is ignore_until:
|
|
|
|
for token in self.tokens(previous, None):
|
|
|
|
yield token
|
|
|
|
elif ignore_until is not None:
|
|
|
|
raise ValueError("Illformed DOM event stream: void element without END_ELEMENT")
|
|
|
|
|
|
|
|
def tokens(self, event, next):
|
|
|
|
type, node = event
|
|
|
|
if type == START_ELEMENT:
|
|
|
|
name = node.nodeName
|
|
|
|
namespace = node.namespaceURI
|
|
|
|
attrs = {}
|
2014-07-21 19:01:46 -04:00
|
|
|
for attr in list(node.attributes.keys()):
|
2014-03-10 01:18:05 -04:00
|
|
|
attr = node.getAttributeNode(attr)
|
2014-07-21 19:01:46 -04:00
|
|
|
attrs[(attr.namespaceURI, attr.localName)] = attr.value
|
2014-03-10 01:18:05 -04:00
|
|
|
if name in voidElements:
|
|
|
|
for token in self.emptyTag(namespace,
|
|
|
|
name,
|
|
|
|
attrs,
|
|
|
|
not next or next[1] is not node):
|
|
|
|
yield token
|
|
|
|
else:
|
|
|
|
yield self.startTag(namespace, name, attrs)
|
|
|
|
|
|
|
|
elif type == END_ELEMENT:
|
|
|
|
name = node.nodeName
|
|
|
|
namespace = node.namespaceURI
|
|
|
|
if name not in voidElements:
|
|
|
|
yield self.endTag(namespace, name)
|
|
|
|
|
|
|
|
elif type == COMMENT:
|
|
|
|
yield self.comment(node.nodeValue)
|
|
|
|
|
|
|
|
elif type in (IGNORABLE_WHITESPACE, CHARACTERS):
|
|
|
|
for token in self.text(node.nodeValue):
|
|
|
|
yield token
|
|
|
|
|
|
|
|
else:
|
|
|
|
yield self.unknown(type)
|