Skip to content

dict

xsdata.formats.dataclass.parsers.dict

DictDecoder dataclass

Bind a dictionary or a list of dictionaries to data models.

Parameters:

Name Type Description Default
config ParserConfig

Parser configuration

ParserConfig()
context XmlContext

The models context instance

XmlContext()
Source code in xsdata/formats/dataclass/parsers/dict.py
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
@dataclass
class DictDecoder:
    """Bind a dictionary or a list of dictionaries to data models.

    Args:
        config: Parser configuration
        context: The models context instance
    """

    config: ParserConfig = field(default_factory=ParserConfig)
    context: XmlContext = field(default_factory=XmlContext)

    def decode(self, data: Union[List, Dict], clazz: Optional[Type[T]] = None) -> T:
        """Parse the input stream into the target class type.

        If no clazz is provided, the binding context will try
        to locate it from imported dataclasses.

        Args:
            data: A dictionary or list of dictionaries
            clazz: The target class type to decode the input data

        Returns:
            An instance of the specified class representing the decoded content.
        """
        tp = self.verify_type(clazz, data)
        if not isinstance(data, list):
            return self.bind_dataclass(data, tp)

        return [self.bind_dataclass(obj, tp) for obj in data]  # type: ignore

    def verify_type(self, clazz: Optional[Type[T]], data: Union[Dict, List]) -> Type[T]:
        """Verify the given data matches the given clazz.

        If no clazz is provided, the binding context will try
        to locate it from imported dataclasses.

        Args:
            clazz: The target class type to parse  object
            data: The loaded dictionary or list of dictionaries

        Returns:
            The clazz type to bind the loaded data.
        """
        if clazz is None:
            return self.detect_type(data)

        try:
            origin = get_origin(clazz)
            list_type = False
            if origin is list:
                list_type = True
                args = get_args(clazz)

                if len(args) != 1 or not self.context.class_type.is_model(args[0]):
                    raise TypeError()

                clazz = args[0]
            elif origin is not None:
                raise TypeError()
        except TypeError:
            raise ParserError(f"Invalid clazz argument: {clazz}")

        if list_type != isinstance(data, list):
            if list_type:
                raise ParserError("Document is object, expected array")
            raise ParserError("Document is array, expected object")

        return clazz  # type: ignore

    def detect_type(self, data: Union[Dict, List]) -> Type[T]:
        """Locate the target clazz type from the data keys.

        Args:
            data: The loaded dictionary or list of dictionaries

        Returns:
            The clazz type to bind the loaded data.
        """
        if not data:
            raise ParserError("Document is empty, can not detect type")

        keys = data[0].keys() if isinstance(data, list) else data.keys()
        clazz: Optional[Type[T]] = self.context.find_type_by_fields(set(keys))

        if clazz:
            return clazz

        raise ParserError(f"Unable to locate model with properties({list(keys)})")

    def bind_dataclass(self, data: Dict, clazz: Type[T]) -> T:
        """Create a new instance of the given class type with the given data.

        Args:
            data: The loaded data
            clazz: The target class type to bind the input data

        Returns:
            An instance of the class type representing the parsed content.
        """
        if set(data.keys()) == self.context.class_type.derived_keys:
            return self.bind_derived_dataclass(data, clazz)

        meta = self.context.build(clazz)
        xml_vars = meta.get_all_vars()

        params = {}
        for key, value in data.items():
            var = self.find_var(xml_vars, key, value)

            if var is None:
                if self.config.fail_on_unknown_properties:
                    raise ParserError(f"Unknown property {clazz.__qualname__}.{key}")
                else:
                    continue

            if var.wrapper:
                value = value[var.local_name]

            value = self.bind_value(meta, var, value)
            if var.init:
                params[var.name] = value
            else:
                ParserUtils.validate_fixed_value(meta, var, value)

        try:
            return self.config.class_factory(clazz, params)
        except TypeError as e:
            raise ParserError(e)

    def bind_derived_dataclass(self, data: Dict, clazz: Type[T]) -> Any:
        """Bind the input data to the given class type.

        Examples:
            {
                "qname": "foo",
                "type": "my:type",
                "value": {"prop": "value"}
            }

        Args:
            data: The derived element dictionary
            clazz: The target class type to bind the input data

        Returns:
            An instance of the class type representing the parsed content.
        """
        qname = data["qname"]
        xsi_type = data["type"]
        params = data["value"]

        generic = self.context.class_type.derived_element

        if clazz is generic:
            real_clazz: Optional[Type[T]] = None
            if xsi_type:
                real_clazz = self.context.find_type(xsi_type)

            if real_clazz is None:
                raise ParserError(
                    f"Unable to locate derived model "
                    f"with properties({list(params.keys())})"
                )

            value = self.bind_dataclass(params, real_clazz)
        else:
            value = self.bind_dataclass(params, clazz)

        return generic(qname=qname, type=xsi_type, value=value)

    def bind_best_dataclass(self, data: Dict, classes: Iterable[Type[T]]) -> T:
        """Bind the input data to all the given classes and return best match.

        Args:
            data: The derived element dictionary
            classes: The target class types to try

        Returns:
            An instance of one of the class types representing the parsed content.
        """
        obj = None
        keys = set(data.keys())
        max_score = -1.0
        config = replace(self.config, fail_on_converter_warnings=True)
        decoder = DictDecoder(config=config, context=self.context)

        for clazz in classes:
            if not self.context.class_type.is_model(clazz):
                continue

            if self.context.local_names_match(keys, clazz):
                candidate = None
                with suppress(Exception):
                    candidate = decoder.bind_dataclass(data, clazz)

                score = self.context.class_type.score_object(candidate)
                if score > max_score:
                    max_score = score
                    obj = candidate

        if obj:
            return obj

        raise ParserError(
            f"Failed to bind object with properties({list(data.keys())}) "
            f"to any of the {[cls.__qualname__ for cls in classes]}"
        )

    def bind_value(
        self,
        meta: XmlMeta,
        var: XmlVar,
        value: Any,
        recursive: bool = False,
    ) -> Any:
        """Main entry point for binding values.

        Args:
            meta: The parent xml meta instance
            var: The xml var descriptor for the field
            value: The data value
            recursive: Whether this is a recursive call

        Returns:
            The parsed object
        """
        # xs:anyAttributes get it out of the way, it's the mapping exception!
        if var.is_attributes:
            return dict(value)

        # Repeating element, recursively bind the values
        if not recursive and var.list_element and isinstance(value, list):
            assert var.factory is not None
            return var.factory(
                self.bind_value(meta, var, val, recursive=True) for val in value
            )

        # If not dict this is a text or tokens value.
        if not isinstance(value, dict):
            return self.bind_text(meta, var, value)

        keys = value.keys()
        if keys == self.context.class_type.any_keys:
            # Bind data to AnyElement dataclass
            return self.bind_dataclass(value, self.context.class_type.any_element)

        if keys == self.context.class_type.derived_keys:
            # Bind data to AnyElement dataclass
            return self.bind_derived_value(meta, var, value)

        # Bind data to a user defined dataclass
        return self.bind_complex_type(meta, var, value)

    def bind_text(self, meta: XmlMeta, var: XmlVar, value: Any) -> Any:
        """Bind text/tokens value entrypoint.

        Args:
            meta: The parent xml meta instance
            var: The xml var descriptor for the field
            value: The data value

        Returns:
            The parsed tokens or text value.
        """
        if var.is_elements:
            # Compound field we need to match the value to one of the choice elements
            check_subclass = self.context.class_type.is_model(value)
            choice = var.find_value_choice(value, check_subclass)
            if choice:
                return self.bind_text(meta, choice, value)

            if value is None:
                return value

            raise ParserError(
                f"Failed to bind '{value}' "
                f"to {meta.clazz.__qualname__}.{var.name} field"
            )

        if var.any_type or var.is_wildcard:
            # field can support any object return the value as it is
            return value

        value = converter.serialize(value)

        # Convert value according to the field types
        return ParserUtils.parse_var(
            meta=meta,
            var=var,
            config=self.config,
            value=value,
            ns_map=EMPTY_MAP,
        )

    def bind_complex_type(self, meta: XmlMeta, var: XmlVar, data: Dict) -> Any:
        """Bind complex values entrypoint.

        Args:
            meta: The parent xml meta instance
            var: The xml var descriptor for the field
            data: The complex data value

        Returns:
            The parsed dataclass instance.
        """
        if var.is_clazz_union:
            # Union of dataclasses
            return self.bind_best_dataclass(data, var.types)
        if var.elements:
            # Compound field with multiple choices
            return self.bind_best_dataclass(data, var.element_types)
        if var.any_type or var.is_wildcard:
            # xs:anyType element, check all meta classes
            return self.bind_best_dataclass(data, meta.element_types)

        assert var.clazz is not None

        subclasses = set(self.context.get_subclasses(var.clazz))
        if subclasses:
            # field annotation is an abstract/base type
            subclasses.add(var.clazz)
            return self.bind_best_dataclass(data, subclasses)

        return self.bind_dataclass(data, var.clazz)

    def bind_derived_value(self, meta: XmlMeta, var: XmlVar, data: Dict) -> Any:
        """Bind derived data entrypoint.

        The data is representation of a derived element, e.g. {
            "qname": "foo",
            "type": "my:type"
            "value": Any
        }

        The data value can be a primitive value or a complex value.

        Args:
            meta: The parent xml meta instance
            var: The xml var descriptor for the field
            data: The derived element data

        Returns:
            The parsed object.
        """
        qname = data["qname"]
        xsi_type = data["type"]
        params = data["value"]

        if var.elements:
            choice = var.find_choice(qname)
            if choice is None:
                raise ParserError(
                    f"Unable to locate compound element"
                    f" {meta.clazz.__qualname__}.{var.name}[{qname}]"
                )
            return self.bind_derived_value(meta, choice, data)

        if not isinstance(params, dict):
            # Is this scenario still possible???
            value = self.bind_text(meta, var, params)
        elif xsi_type:
            clazz: Optional[Type] = self.context.find_type(xsi_type)

            if clazz is None:
                raise ParserError(f"Unable to locate xsi:type `{xsi_type}`")

            value = self.bind_dataclass(params, clazz)
        elif var.clazz:
            value = self.bind_complex_type(meta, var, params)
        else:
            value = self.bind_best_dataclass(params, meta.element_types)

        generic = self.context.class_type.derived_element
        return generic(qname=qname, value=value, type=xsi_type)

    @classmethod
    def find_var(
        cls,
        xml_vars: List[XmlVar],
        key: str,
        value: Any,
    ) -> Optional[XmlVar]:
        """Match the name to a xml variable.

        Args:
            xml_vars: A list of xml vars
            key: A key from the loaded data
            value: The data assigned to the key

        Returns:
            One of the xml vars, if all search attributes match, None otherwise.
        """
        for var in xml_vars:
            if var.local_name == key:
                var_is_list = var.list_element or var.tokens
                is_array = collections.is_array(value)
                if is_array == var_is_list:
                    return var
            elif var.wrapper == key:
                if isinstance(value, dict) and var.local_name in value:
                    val = value[var.local_name]
                    var_is_list = var.list_element or var.tokens
                    is_array = collections.is_array(val)
                    if is_array == var_is_list:
                        return var
        return None

decode(data, clazz=None)

Parse the input stream into the target class type.

If no clazz is provided, the binding context will try to locate it from imported dataclasses.

Parameters:

Name Type Description Default
data Union[List, Dict]

A dictionary or list of dictionaries

required
clazz Optional[Type[T]]

The target class type to decode the input data

None

Returns:

Type Description
T

An instance of the specified class representing the decoded content.

Source code in xsdata/formats/dataclass/parsers/dict.py
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
def decode(self, data: Union[List, Dict], clazz: Optional[Type[T]] = None) -> T:
    """Parse the input stream into the target class type.

    If no clazz is provided, the binding context will try
    to locate it from imported dataclasses.

    Args:
        data: A dictionary or list of dictionaries
        clazz: The target class type to decode the input data

    Returns:
        An instance of the specified class representing the decoded content.
    """
    tp = self.verify_type(clazz, data)
    if not isinstance(data, list):
        return self.bind_dataclass(data, tp)

    return [self.bind_dataclass(obj, tp) for obj in data]  # type: ignore

verify_type(clazz, data)

Verify the given data matches the given clazz.

If no clazz is provided, the binding context will try to locate it from imported dataclasses.

Parameters:

Name Type Description Default
clazz Optional[Type[T]]

The target class type to parse object

required
data Union[Dict, List]

The loaded dictionary or list of dictionaries

required

Returns:

Type Description
Type[T]

The clazz type to bind the loaded data.

Source code in xsdata/formats/dataclass/parsers/dict.py
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
def verify_type(self, clazz: Optional[Type[T]], data: Union[Dict, List]) -> Type[T]:
    """Verify the given data matches the given clazz.

    If no clazz is provided, the binding context will try
    to locate it from imported dataclasses.

    Args:
        clazz: The target class type to parse  object
        data: The loaded dictionary or list of dictionaries

    Returns:
        The clazz type to bind the loaded data.
    """
    if clazz is None:
        return self.detect_type(data)

    try:
        origin = get_origin(clazz)
        list_type = False
        if origin is list:
            list_type = True
            args = get_args(clazz)

            if len(args) != 1 or not self.context.class_type.is_model(args[0]):
                raise TypeError()

            clazz = args[0]
        elif origin is not None:
            raise TypeError()
    except TypeError:
        raise ParserError(f"Invalid clazz argument: {clazz}")

    if list_type != isinstance(data, list):
        if list_type:
            raise ParserError("Document is object, expected array")
        raise ParserError("Document is array, expected object")

    return clazz  # type: ignore

detect_type(data)

Locate the target clazz type from the data keys.

Parameters:

Name Type Description Default
data Union[Dict, List]

The loaded dictionary or list of dictionaries

required

Returns:

Type Description
Type[T]

The clazz type to bind the loaded data.

Source code in xsdata/formats/dataclass/parsers/dict.py
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
def detect_type(self, data: Union[Dict, List]) -> Type[T]:
    """Locate the target clazz type from the data keys.

    Args:
        data: The loaded dictionary or list of dictionaries

    Returns:
        The clazz type to bind the loaded data.
    """
    if not data:
        raise ParserError("Document is empty, can not detect type")

    keys = data[0].keys() if isinstance(data, list) else data.keys()
    clazz: Optional[Type[T]] = self.context.find_type_by_fields(set(keys))

    if clazz:
        return clazz

    raise ParserError(f"Unable to locate model with properties({list(keys)})")

bind_dataclass(data, clazz)

Create a new instance of the given class type with the given data.

Parameters:

Name Type Description Default
data Dict

The loaded data

required
clazz Type[T]

The target class type to bind the input data

required

Returns:

Type Description
T

An instance of the class type representing the parsed content.

Source code in xsdata/formats/dataclass/parsers/dict.py
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
def bind_dataclass(self, data: Dict, clazz: Type[T]) -> T:
    """Create a new instance of the given class type with the given data.

    Args:
        data: The loaded data
        clazz: The target class type to bind the input data

    Returns:
        An instance of the class type representing the parsed content.
    """
    if set(data.keys()) == self.context.class_type.derived_keys:
        return self.bind_derived_dataclass(data, clazz)

    meta = self.context.build(clazz)
    xml_vars = meta.get_all_vars()

    params = {}
    for key, value in data.items():
        var = self.find_var(xml_vars, key, value)

        if var is None:
            if self.config.fail_on_unknown_properties:
                raise ParserError(f"Unknown property {clazz.__qualname__}.{key}")
            else:
                continue

        if var.wrapper:
            value = value[var.local_name]

        value = self.bind_value(meta, var, value)
        if var.init:
            params[var.name] = value
        else:
            ParserUtils.validate_fixed_value(meta, var, value)

    try:
        return self.config.class_factory(clazz, params)
    except TypeError as e:
        raise ParserError(e)

bind_derived_dataclass(data, clazz)

Bind the input data to the given class type.

Examples:

{ "qname": "foo", "type": "my:type", "value": {"prop": "value"} }

Parameters:

Name Type Description Default
data Dict

The derived element dictionary

required
clazz Type[T]

The target class type to bind the input data

required

Returns:

Type Description
Any

An instance of the class type representing the parsed content.

Source code in xsdata/formats/dataclass/parsers/dict.py
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
def bind_derived_dataclass(self, data: Dict, clazz: Type[T]) -> Any:
    """Bind the input data to the given class type.

    Examples:
        {
            "qname": "foo",
            "type": "my:type",
            "value": {"prop": "value"}
        }

    Args:
        data: The derived element dictionary
        clazz: The target class type to bind the input data

    Returns:
        An instance of the class type representing the parsed content.
    """
    qname = data["qname"]
    xsi_type = data["type"]
    params = data["value"]

    generic = self.context.class_type.derived_element

    if clazz is generic:
        real_clazz: Optional[Type[T]] = None
        if xsi_type:
            real_clazz = self.context.find_type(xsi_type)

        if real_clazz is None:
            raise ParserError(
                f"Unable to locate derived model "
                f"with properties({list(params.keys())})"
            )

        value = self.bind_dataclass(params, real_clazz)
    else:
        value = self.bind_dataclass(params, clazz)

    return generic(qname=qname, type=xsi_type, value=value)

bind_best_dataclass(data, classes)

Bind the input data to all the given classes and return best match.

Parameters:

Name Type Description Default
data Dict

The derived element dictionary

required
classes Iterable[Type[T]]

The target class types to try

required

Returns:

Type Description
T

An instance of one of the class types representing the parsed content.

Source code in xsdata/formats/dataclass/parsers/dict.py
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
def bind_best_dataclass(self, data: Dict, classes: Iterable[Type[T]]) -> T:
    """Bind the input data to all the given classes and return best match.

    Args:
        data: The derived element dictionary
        classes: The target class types to try

    Returns:
        An instance of one of the class types representing the parsed content.
    """
    obj = None
    keys = set(data.keys())
    max_score = -1.0
    config = replace(self.config, fail_on_converter_warnings=True)
    decoder = DictDecoder(config=config, context=self.context)

    for clazz in classes:
        if not self.context.class_type.is_model(clazz):
            continue

        if self.context.local_names_match(keys, clazz):
            candidate = None
            with suppress(Exception):
                candidate = decoder.bind_dataclass(data, clazz)

            score = self.context.class_type.score_object(candidate)
            if score > max_score:
                max_score = score
                obj = candidate

    if obj:
        return obj

    raise ParserError(
        f"Failed to bind object with properties({list(data.keys())}) "
        f"to any of the {[cls.__qualname__ for cls in classes]}"
    )

bind_value(meta, var, value, recursive=False)

Main entry point for binding values.

Parameters:

Name Type Description Default
meta XmlMeta

The parent xml meta instance

required
var XmlVar

The xml var descriptor for the field

required
value Any

The data value

required
recursive bool

Whether this is a recursive call

False

Returns:

Type Description
Any

The parsed object

Source code in xsdata/formats/dataclass/parsers/dict.py
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
def bind_value(
    self,
    meta: XmlMeta,
    var: XmlVar,
    value: Any,
    recursive: bool = False,
) -> Any:
    """Main entry point for binding values.

    Args:
        meta: The parent xml meta instance
        var: The xml var descriptor for the field
        value: The data value
        recursive: Whether this is a recursive call

    Returns:
        The parsed object
    """
    # xs:anyAttributes get it out of the way, it's the mapping exception!
    if var.is_attributes:
        return dict(value)

    # Repeating element, recursively bind the values
    if not recursive and var.list_element and isinstance(value, list):
        assert var.factory is not None
        return var.factory(
            self.bind_value(meta, var, val, recursive=True) for val in value
        )

    # If not dict this is a text or tokens value.
    if not isinstance(value, dict):
        return self.bind_text(meta, var, value)

    keys = value.keys()
    if keys == self.context.class_type.any_keys:
        # Bind data to AnyElement dataclass
        return self.bind_dataclass(value, self.context.class_type.any_element)

    if keys == self.context.class_type.derived_keys:
        # Bind data to AnyElement dataclass
        return self.bind_derived_value(meta, var, value)

    # Bind data to a user defined dataclass
    return self.bind_complex_type(meta, var, value)

bind_text(meta, var, value)

Bind text/tokens value entrypoint.

Parameters:

Name Type Description Default
meta XmlMeta

The parent xml meta instance

required
var XmlVar

The xml var descriptor for the field

required
value Any

The data value

required

Returns:

Type Description
Any

The parsed tokens or text value.

Source code in xsdata/formats/dataclass/parsers/dict.py
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
def bind_text(self, meta: XmlMeta, var: XmlVar, value: Any) -> Any:
    """Bind text/tokens value entrypoint.

    Args:
        meta: The parent xml meta instance
        var: The xml var descriptor for the field
        value: The data value

    Returns:
        The parsed tokens or text value.
    """
    if var.is_elements:
        # Compound field we need to match the value to one of the choice elements
        check_subclass = self.context.class_type.is_model(value)
        choice = var.find_value_choice(value, check_subclass)
        if choice:
            return self.bind_text(meta, choice, value)

        if value is None:
            return value

        raise ParserError(
            f"Failed to bind '{value}' "
            f"to {meta.clazz.__qualname__}.{var.name} field"
        )

    if var.any_type or var.is_wildcard:
        # field can support any object return the value as it is
        return value

    value = converter.serialize(value)

    # Convert value according to the field types
    return ParserUtils.parse_var(
        meta=meta,
        var=var,
        config=self.config,
        value=value,
        ns_map=EMPTY_MAP,
    )

bind_complex_type(meta, var, data)

Bind complex values entrypoint.

Parameters:

Name Type Description Default
meta XmlMeta

The parent xml meta instance

required
var XmlVar

The xml var descriptor for the field

required
data Dict

The complex data value

required

Returns:

Type Description
Any

The parsed dataclass instance.

Source code in xsdata/formats/dataclass/parsers/dict.py
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
def bind_complex_type(self, meta: XmlMeta, var: XmlVar, data: Dict) -> Any:
    """Bind complex values entrypoint.

    Args:
        meta: The parent xml meta instance
        var: The xml var descriptor for the field
        data: The complex data value

    Returns:
        The parsed dataclass instance.
    """
    if var.is_clazz_union:
        # Union of dataclasses
        return self.bind_best_dataclass(data, var.types)
    if var.elements:
        # Compound field with multiple choices
        return self.bind_best_dataclass(data, var.element_types)
    if var.any_type or var.is_wildcard:
        # xs:anyType element, check all meta classes
        return self.bind_best_dataclass(data, meta.element_types)

    assert var.clazz is not None

    subclasses = set(self.context.get_subclasses(var.clazz))
    if subclasses:
        # field annotation is an abstract/base type
        subclasses.add(var.clazz)
        return self.bind_best_dataclass(data, subclasses)

    return self.bind_dataclass(data, var.clazz)

bind_derived_value(meta, var, data)

Bind derived data entrypoint.

The data is representation of a derived element, e.g. { "qname": "foo", "type": "my:type" "value": Any }

The data value can be a primitive value or a complex value.

Parameters:

Name Type Description Default
meta XmlMeta

The parent xml meta instance

required
var XmlVar

The xml var descriptor for the field

required
data Dict

The derived element data

required

Returns:

Type Description
Any

The parsed object.

Source code in xsdata/formats/dataclass/parsers/dict.py
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
def bind_derived_value(self, meta: XmlMeta, var: XmlVar, data: Dict) -> Any:
    """Bind derived data entrypoint.

    The data is representation of a derived element, e.g. {
        "qname": "foo",
        "type": "my:type"
        "value": Any
    }

    The data value can be a primitive value or a complex value.

    Args:
        meta: The parent xml meta instance
        var: The xml var descriptor for the field
        data: The derived element data

    Returns:
        The parsed object.
    """
    qname = data["qname"]
    xsi_type = data["type"]
    params = data["value"]

    if var.elements:
        choice = var.find_choice(qname)
        if choice is None:
            raise ParserError(
                f"Unable to locate compound element"
                f" {meta.clazz.__qualname__}.{var.name}[{qname}]"
            )
        return self.bind_derived_value(meta, choice, data)

    if not isinstance(params, dict):
        # Is this scenario still possible???
        value = self.bind_text(meta, var, params)
    elif xsi_type:
        clazz: Optional[Type] = self.context.find_type(xsi_type)

        if clazz is None:
            raise ParserError(f"Unable to locate xsi:type `{xsi_type}`")

        value = self.bind_dataclass(params, clazz)
    elif var.clazz:
        value = self.bind_complex_type(meta, var, params)
    else:
        value = self.bind_best_dataclass(params, meta.element_types)

    generic = self.context.class_type.derived_element
    return generic(qname=qname, value=value, type=xsi_type)

find_var(xml_vars, key, value) classmethod

Match the name to a xml variable.

Parameters:

Name Type Description Default
xml_vars List[XmlVar]

A list of xml vars

required
key str

A key from the loaded data

required
value Any

The data assigned to the key

required

Returns:

Type Description
Optional[XmlVar]

One of the xml vars, if all search attributes match, None otherwise.

Source code in xsdata/formats/dataclass/parsers/dict.py
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
@classmethod
def find_var(
    cls,
    xml_vars: List[XmlVar],
    key: str,
    value: Any,
) -> Optional[XmlVar]:
    """Match the name to a xml variable.

    Args:
        xml_vars: A list of xml vars
        key: A key from the loaded data
        value: The data assigned to the key

    Returns:
        One of the xml vars, if all search attributes match, None otherwise.
    """
    for var in xml_vars:
        if var.local_name == key:
            var_is_list = var.list_element or var.tokens
            is_array = collections.is_array(value)
            if is_array == var_is_list:
                return var
        elif var.wrapper == key:
            if isinstance(value, dict) and var.local_name in value:
                val = value[var.local_name]
                var_is_list = var.list_element or var.tokens
                is_array = collections.is_array(val)
                if is_array == var_is_list:
                    return var
    return None