def test_xsi_type(self): ns_map = {"bar": "xsdata"} attrs = {} self.assertIsNone(ParserUtils.xsi_type(attrs, ns_map)) attrs = {QNames.XSI_TYPE: "foo"} self.assertEqual("foo", ParserUtils.xsi_type(attrs, ns_map)) attrs = {QNames.XSI_TYPE: "bar:foo"} self.assertEqual("{xsdata}foo", ParserUtils.xsi_type(attrs, ns_map))
def start( self, clazz: Optional[Type], queue: List[XmlNode], objects: List[Parsed], qname: str, attrs: Dict, ns_map: Dict, ): """ Start element notification receiver. Build and queue the XmlNode for the starting element. :param clazz: Root class type, if it's missing look for any suitable models from the current context. :param queue: The active XmlNode queue :param objects: The list of all intermediate parsed objects :param qname: Qualified name :param attrs: Attribute key-value map :param ns_map: Namespace prefix-URI map """ try: item = queue[-1] child = item.child(qname, attrs, ns_map, len(objects)) except IndexError: xsi_type = ParserUtils.xsi_type(attrs, ns_map) # Match element qname directly if clazz is None: clazz = self.context.find_type(qname) # Root is xs:anyType try xsi:type if clazz is None and xsi_type: clazz = self.context.find_type(xsi_type) # Exit if we still have no binding model if clazz is None: raise ParserError(f"No class found matching root: {qname}") meta = self.context.fetch(clazz, xsi_type=xsi_type) derived = xsi_type is not None and meta.qname != qname child = ElementNode( position=0, meta=meta, config=self.config, attrs=attrs, ns_map=ns_map, context=self.context, derived=derived, ) queue.append(child)
def build_node(self, var: XmlVar, attrs: Dict, ns_map: Dict, position: int) -> Optional[XmlNode]: if var.is_clazz_union: return UnionNode( var=var, attrs=attrs, ns_map=ns_map, context=self.context, position=position, ) xsi_type = ParserUtils.xsi_type(attrs, ns_map) if var.clazz: return self.build_element_node( var.clazz, attrs, ns_map, position, var.derived, xsi_type, ) if not var.any_type and not var.wildcard: return PrimitiveNode(var, ns_map) datatype = DataType.from_qname(xsi_type) if xsi_type else None derived = var.derived or var.wildcard if datatype: return StandardNode(datatype, ns_map, derived, var.nillable) node = None clazz = None if xsi_type: clazz = self.context.find_type(xsi_type) if clazz: node = self.build_element_node(clazz, attrs, ns_map, position, derived, xsi_type) if node: return node return WildcardNode(var=var, attrs=attrs, ns_map=ns_map, position=position)
def build_element_node( self, clazz: Optional[Type], attrs: Dict, ns_map: Dict, position: int, derived: bool, ) -> Optional[XmlNode]: xsi_type = ParserUtils.xsi_type(attrs, ns_map) if clazz is None: if not xsi_type: return None clazz = self.context.find_type(xsi_type) xsi_type = None if clazz is None: return None is_nillable = ParserUtils.is_nillable(attrs) meta = self.context.fetch(clazz, self.meta.namespace, xsi_type) if not is_nillable and meta.nillable: return None return ElementNode( meta=meta, config=self.config, attrs=attrs, ns_map=ns_map, context=self.context, position=position, derived=derived, mixed=self.meta.has_var(mode=FindMode.MIXED_CONTENT), )