diff options
| author | Michael Williamson <mike@zwobble.org> | 2013-12-01 00:42:19 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2013-12-01 00:42:19 +0000 |
| commit | 2c07fef611dd1d5cd7e83d59d02d5ab52db74e63 (patch) | |
| tree | 91e69988641f0e890cef9e70c4a2fb39d5d499eb /mammoth/xmlparser.py | |
| parent | 73a80869afb8f2e4c7727150a0ea211b93ccc475 (diff) | |
Add xmlparser
Diffstat (limited to 'mammoth/xmlparser.py')
| -rw-r--r-- | mammoth/xmlparser.py | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/mammoth/xmlparser.py b/mammoth/xmlparser.py new file mode 100644 index 0000000..bd344a0 --- /dev/null +++ b/mammoth/xmlparser.py @@ -0,0 +1,69 @@ +import collections +import xml.sax + + +XmlElement = collections.namedtuple("XmlElement", ["name", "attributes", "children"]) +XmlText = collections.namedtuple("XmlText", ["value"]) + + +element = XmlElement +text = XmlText + + +def parse_xml(fileobj, namespace_mapping=None): + if namespace_mapping is None: + namespace_prefixes = {} + else: + namespace_prefixes = dict((uri, prefix) for prefix, uri in namespace_mapping) + + handler = Handler(namespace_prefixes) + parser = xml.sax.make_parser() + parser.setFeature(xml.sax.handler.feature_namespaces, True) + parser.setContentHandler(handler) + parser.parse(fileobj) + return handler.root() + + +class Handler(xml.sax.handler.ContentHandler): + def __init__(self, namespace_prefixes): + self._namespace_prefixes = namespace_prefixes + self._element_stack = [RootElement()] + self._character_buffer = [] + + def root(self): + return self._element_stack[0].children[0] + + def startElementNS(self, name, qname, attrs): + self._flush_character_buffer() + attributes = dict((self._read_name(key), value) for key, value in attrs.items()) + element = XmlElement(self._read_name(name), attributes, []) + self._element_stack[-1].children.append(element) + self._element_stack.append(element) + + def endElementNS(self, name, qname): + self._flush_character_buffer() + self._element_stack.pop() + + def characters(self, content): + self._character_buffer.append(content) + + def _flush_character_buffer(self): + if self._character_buffer: + text = "".join(self._character_buffer) + self._element_stack[-1].children.append(XmlText(text)) + self._character_buffer = [] + + def _read_name(self, name): + uri, local_name = name + if uri is None: + return local_name + else: + prefix = self._namespace_prefixes.get(uri) + if prefix is None: + return "{%s}%s" % (uri, local_name) + else: + return "%s:%s" % (prefix, local_name) + +class RootElement(object): + def __init__(self): + self.children = [] |
