From 09657ab70b3cdbb334e38c380692a495770a4c02 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sun, 28 May 2023 20:05:46 +0100 Subject: Use xml.dom.minidom instead of xml.sax --- mammoth/docx/xmlparser.py | 101 ++++++++++++++++++++-------------------------- 1 file changed, 44 insertions(+), 57 deletions(-) (limited to 'mammoth') diff --git a/mammoth/docx/xmlparser.py b/mammoth/docx/xmlparser.py index 4e963db..bb84afd 100644 --- a/mammoth/docx/xmlparser.py +++ b/mammoth/docx/xmlparser.py @@ -1,4 +1,4 @@ -import xml.sax +import xml.dom.minidom import cobble @@ -8,16 +8,16 @@ class XmlElement(object): name = cobble.field() attributes = cobble.field() children = cobble.field() - + def find_child_or_null(self, name): return self.find_child(name) or _null_xml_element - + def find_child(self, name): for child in self.children: if isinstance(child, XmlElement) and child.name == name: return child - - + + def find_children(self, name): return XmlElementList(filter( lambda child: child.node_type == node_types.element and child.name == name, @@ -28,10 +28,10 @@ class XmlElement(object): class XmlElementList(object): def __init__(self, elements): self._elements = elements - + def __iter__(self): return iter(self._elements) - + def find_children(self, name): children = [] for element in self._elements: @@ -42,10 +42,10 @@ class XmlElementList(object): class NullXmlElement(object): attributes = {} - + def find_child_or_null(self, name): return self - + def find_child(self, name): return None @@ -79,55 +79,42 @@ def parse_xml(fileobj, namespace_mapping=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 + + document = xml.dom.minidom.parse(fileobj) + + def convert_node(node): + if node.nodeType == xml.dom.Node.ELEMENT_NODE: + return convert_element(node) + elif node.nodeType == xml.dom.Node.TEXT_NODE: + return XmlText(node.nodeValue) + else: + return None + + def convert_element(element): + converted_name = convert_name(element) + + converted_attributes = dict( + (convert_name(attribute), attribute.value) + for attribute in element.attributes.values() + if attribute.namespaceURI != "http://www.w3.org/2000/xmlns/" + ) + + converted_children = [] + for child_node in element.childNodes: + converted_child_node = convert_node(child_node) + if converted_child_node is not None: + converted_children.append(converted_child_node) + + return XmlElement(converted_name, converted_attributes, converted_children) + + def convert_name(node): + if node.namespaceURI is None: + return node.localName else: - prefix = self._namespace_prefixes.get(uri) + prefix = namespace_prefixes.get(node.namespaceURI) if prefix is None: - return "{%s}%s" % (uri, local_name) + return "{%s}%s" % (node.namespaceURI, node.localName) else: - return "%s:%s" % (prefix, local_name) + return "%s:%s" % (prefix, node.localName) -class RootElement(object): - def __init__(self): - self.children = [] + return convert_node(document.documentElement) -- cgit v1.2.3