[docs]classUnionNode(XmlNode):""" XmlNode for fields with multiple possible types where at least one of them is a dataclass. The node will record all child events and in the end will replay them and try to build all possible objects and sort them by score before deciding the winner. :param var: Class field xml var instance :param attrs: Key-value attribute mapping :param ns_map: Namespace prefix-URI map :param position: The node position of objects cache :param config: Parser configuration :param context: Model context provider """__slots__=("var","attrs","ns_map","position","config","context","level","events",)def__init__(self,var:XmlVar,attrs:Dict,ns_map:Dict,position:int,config:ParserConfig,context:XmlContext,):self.var=varself.attrs=attrsself.ns_map=ns_mapself.position=positionself.config=configself.context=contextself.level=0self.events:List[Tuple[str,str,Any,Any]]=[]
[docs]defbind(self,qname:str,text:Optional[str],tail:Optional[str],objects:List)->bool:self.events.append(("end",qname,text,tail))ifself.level>0:self.level-=1returnFalseself.events.insert(0,("start",qname,copy.deepcopy(self.attrs),self.ns_map))obj=Nonemax_score=-1.0parent_namespace=target_uri(qname)forclazzinself.var.types:ifself.context.class_type.is_model(clazz):self.context.build(clazz,parent_ns=parent_namespace)candidate=self.parse_class(clazz)else:candidate=self.parse_value(text,[clazz])score=self.context.class_type.score_object(candidate)ifscore>max_score:max_score=scoreobj=candidateifobj:objects.append((self.var.qname,obj))returnTrueraiseParserError(f"Failed to parse union node: {self.var.qname}")
[docs]defparse_class(self,clazz:Type[T])->Optional[T]:"""Initialize a new XmlParser and try to parse the given element, treat converter warnings as errors and return None."""try:withwarnings.catch_warnings():warnings.filterwarnings("error",category=ConverterWarning)parser=NodeParser(config=self.config,context=self.context,handler=EventsHandler)returnparser.parse(self.events,clazz)exceptException:returnNone
[docs]defparse_value(self,value:Any,types:List[Type])->Any:"""Parse simple values, treat warnings as errors and return None."""try:withwarnings.catch_warnings():warnings.filterwarnings("error",category=ConverterWarning)returnParserUtils.parse_value(value=value,types=types,ns_map=self.ns_map)exceptException:returnNone