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

from dataclasses import dataclass
from typing import Any
from typing import Dict
from typing import List
from typing import Tuple
from typing import Type

from lxml.etree import Element
from lxml.etree import QName

from xsdata.exceptions import XmlContextError
from xsdata.formats.dataclass.context import XmlContext
from xsdata.formats.dataclass.models.elements import XmlMeta
from xsdata.formats.dataclass.parsers.utils import ParserUtils


[docs]@dataclass(frozen=True) class XmlNode: index: int position: int
[docs] def next_node( self, qname: QName, index: int, position: int, context: XmlContext ) -> "XmlNode": raise NotImplementedError(f"Not Implemented")
[docs] def parse_element(self, element: Element, objects: List[Any]) -> Tuple: raise NotImplementedError(f"Not Implemented {element.tag}.")
[docs]@dataclass(frozen=True) class ElementNode(XmlNode): meta: XmlMeta default: Any
[docs] def parse_element(self, element: Element, objects: List[Any]) -> Tuple: params: Dict = dict() ParserUtils.bind_element_attrs(params, self.meta, element) ParserUtils.bind_element_text(params, self.meta, element) ParserUtils.bind_element_children(params, self.meta, self.position, objects) ParserUtils.bind_element_wild_text(params, self.meta, element) qname = QName(element.tag) obj = self.meta.clazz(**params) return qname, obj
[docs] def next_node( self, qname: QName, index: int, position: int, context: XmlContext ) -> XmlNode: var = self.meta.find_var(qname) if not var: raise XmlContextError( f"{self.meta.qname} does not support mixed content: {qname}" ) if var.dataclass: return ElementNode( index=index, position=position, meta=context.build(var.clazz, self.meta.qname.namespace), default=var.default, ) if var.is_any_type: return WildcardNode(index=index, position=position, qname=var.qname) return PrimitiveNode( index=index, position=position, types=var.types, default=var.default, tokens=var.is_tokens, )
[docs]@dataclass(frozen=True) class RootNode(ElementNode):
[docs] def next_node( self, qname: QName, index: int, position: int, context: XmlContext ) -> XmlNode: if index == 0: return self return super(RootNode, self).next_node(qname, index, position, context)
[docs]@dataclass(frozen=True) class WildcardNode(XmlNode): qname: str
[docs] def parse_element(self, element: Element, objects: List[Any]) -> Tuple: obj = ParserUtils.parse_any_element(element) obj.children = ParserUtils.fetch_any_children(self.position, objects) return self.qname, obj
[docs] def next_node( self, qname: QName, index: int, position: int, context: XmlContext ) -> XmlNode: return WildcardNode(index=index, position=position, qname=self.qname)
[docs]@dataclass(frozen=True) class SkipNode(XmlNode):
[docs] def parse_element(self, element: Element, objects: List) -> Tuple: return None, None
[docs] @classmethod def next_node( cls, qname: QName, index: int, position: int, context: XmlContext ) -> XmlNode: return SkipNode(index=index, position=position)
[docs]@dataclass(frozen=True) class PrimitiveNode(XmlNode): types: List[Type] tokens: bool = False default: Any = None
[docs] def parse_element(self, element: Element, objects: List) -> Tuple: qname = QName(element.tag) value = element.text ns_map = element.nsmap obj = ParserUtils.parse_value( self.types, value, self.default, ns_map, self.tokens ) return qname, obj
[docs] def next_node( self, qname: QName, index: int, position: int, context: XmlContext ) -> XmlNode: return SkipNode(index=index, position=position)