Source code for xsdata.formats.dataclass.parsers.xml

from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional, Type

from xsdata.formats.dataclass.parsers.bases import NodeParser, Parsed
from xsdata.formats.dataclass.parsers.handlers import default_handler
from xsdata.formats.dataclass.parsers.mixins import XmlHandler, XmlNode
from xsdata.models.enums import EventType
from xsdata.utils.namespaces import local_name
from xsdata.utils.text import snake_case


[docs] @dataclass class XmlParser(NodeParser): """ Default Xml parser for dataclasses. :param config: Parser configuration :param context: Model context provider :param handler: Override default XmlHandler :ivar ms_map: The prefix-URI map generated during parsing """ handler: Type[XmlHandler] = field(default=default_handler())
[docs] @dataclass class UserXmlParser(NodeParser): """ User Xml parser for dataclasses with hooks for emitting events to alter the behavior when an elements starts or ends. :param config: Parser configuration :param context: Model context provider :param handler: Override default XmlHandler :ivar ms_map: The prefix-URI map generated during parsing :ivar emit_cache: Qname to event name cache """ handler: Type[XmlHandler] = field(default=default_handler()) emit_cache: Dict = field(init=False, default_factory=dict)
[docs] def start( self, clazz: Optional[Type], queue: List[XmlNode], objects: List[Parsed], qname: str, attrs: Dict, ns_map: Dict, ): super().start(clazz, queue, objects, qname, attrs, ns_map) self.emit_event(EventType.START, qname, attrs=attrs)
[docs] def end( self, queue: List[XmlNode], objects: List[Parsed], qname: str, text: Optional[str], tail: Optional[str], ) -> bool: result = super().end(queue, objects, qname, text, tail) if result: self.emit_event(EventType.END, qname, obj=objects[-1][1]) return result
[docs] def emit_event(self, event: str, name: str, **kwargs: Any): """ Propagate event to subclasses. Match event and name to a subclass method and trigger it with any input keyword arguments. Example:: event=start, name={urn}bookTitle -> start_booking_title(**kwargs) :param event: Event type start|end :param name: Element qualified name :param kwargs: Event keyword arguments """ key = (event, name) if key not in self.emit_cache: method_name = f"{event}_{snake_case(local_name(name))}" self.emit_cache[key] = getattr(self, method_name, None) method = self.emit_cache[key] if method: method(**kwargs)