Пример #1
0
    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))
Пример #2
0
    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)
Пример #3
0
    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)
Пример #4
0
    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),
        )