1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
|
from collections.abc import Iterator
from lxml import etree
from lxml.sax import ElementTreeContentHandler
from xsdata.formats.dataclass.serializers.mixins import EventContentHandler, XmlWriter
class LxmlEventWriter(XmlWriter):
"""Xml event writer based on `lxml.sax.ElementTreeContentHandler`.
The writer converts the events to a lxml tree which is
then converted to string.
Args:
config: The serializer config instance
output: The output stream to write the result
ns_map: A user defined namespace prefix-URI map
Attributes:
handler: The content handler instance
in_tail: Specifies whether the text content has been written
tail: The current element tail content
attrs: The current element attributes
ns_context: The namespace context queue
pending_tag: The pending element namespace, name tuple
pending_prefixes: The pending element namespace prefixes
"""
def build_handler(self) -> ElementTreeContentHandler:
"""Build the content handler instance.
Returns:
An element tree content handler instance.
"""
return ElementTreeContentHandler()
def write(self, events: Iterator) -> None:
"""Feed the sax content handler with events.
The receiver will also add additional root attributes
like xsi or no namespace location. In the end convert
the handler etree to string based on the configuration.
Args:
events: An iterator of sax events
Raises:
XmlWriterError: On unknown events.
"""
super().write(events)
assert isinstance(self.handler, ElementTreeContentHandler)
if self.config.indent:
etree.indent(self.handler.etree, self.config.indent)
xml = etree.tostring(
self.handler.etree,
encoding=self.config.encoding,
xml_declaration=False,
).decode(self.config.encoding)
self.output.write(xml)
if self.config.indent:
self.output.write("\n")
class LxmlTreeBuilder(EventContentHandler):
"""Tree builder based on `lxml.sax.ElementTreeContentHandler`."""
def build_handler(self) -> ElementTreeContentHandler:
"""Build the content handler instance.
Returns:
An element tree content handler instance.
"""
return ElementTreeContentHandler()
def build(self, events: Iterator) -> etree.ElementTree:
"""Feed the sax content handler with events.
Args:
events: An iterator of sax events
Raises:
XmlWriterError: On unknown events.
Returns:
The element tree instance.
"""
self.write(events)
assert isinstance(self.handler, ElementTreeContentHandler)
if self.config.indent:
etree.indent(self.handler.etree, self.config.indent)
return self.handler.etree
|