Skip to content

utils

xsdata.formats.dataclass.parsers.utils

PendingCollection

Bases: UserList

An iterable implementation of parsed values.

The values are parsed individually in the end we need to convert it to a tuple or a list based on the mutability setting of the data class.

Parameters:

Name Type Description Default
initlist Optional[Iterable]

An initial list of values or None

required
factory Optional[Callable]

A callable factory for the values when the node parse has finished.

required
Source code in xsdata/formats/dataclass/parsers/utils.py
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
class PendingCollection(UserList):
    """An iterable implementation of parsed values.

    The values are parsed individually in the end we
    need to convert it to a tuple or a list based on
    the mutability setting of the data class.

    Args:
        initlist: An initial list of values or None
        factory: A callable factory for the values
            when the node parse has finished.

    """

    def __init__(self, initlist: Optional[Iterable], factory: Optional[Callable]):
        super().__init__(initlist)
        self.factory = factory or list

    def evaluate(self) -> Iterable[Any]:
        """Evaluate the values factory and return the result.

        Returns:
            A list or tuple or set of values
        """
        return self.factory(self.data)

evaluate()

Evaluate the values factory and return the result.

Returns:

Type Description
Iterable[Any]

A list or tuple or set of values

Source code in xsdata/formats/dataclass/parsers/utils.py
39
40
41
42
43
44
45
def evaluate(self) -> Iterable[Any]:
    """Evaluate the values factory and return the result.

    Returns:
        A list or tuple or set of values
    """
    return self.factory(self.data)

ParserUtils

Random parser util functions.

Source code in xsdata/formats/dataclass/parsers/utils.py
 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
class ParserUtils:
    """Random parser util functions."""

    @classmethod
    def xsi_type(cls, attrs: Dict, ns_map: Dict) -> Optional[str]:
        """Parse the xsi:type attribute value if present.

        Args:
            attrs: The element attributes
            ns_map: The element namespace prefix-URI map

        Returns:
            The xsi:type attribute value or None
        """
        xsi_type = attrs.get(QNames.XSI_TYPE)
        if not xsi_type:
            return None

        namespace, name = QNameConverter.resolve(xsi_type, ns_map)
        return build_qname(namespace, name)

    @classmethod
    def xsi_nil(cls, attrs: Dict) -> Optional[bool]:
        """Return whether xsi:nil attribute value.

        Args:
            attrs: The element attributes

        Returns:
            The bool value or None if it doesn't exist.
        """
        xsi_nil = attrs.get(QNames.XSI_NIL)
        return xsi_nil == constants.XML_TRUE if xsi_nil else None

    @classmethod
    def parse_var(
        cls,
        meta: XmlMeta,
        var: XmlVar,
        config: ParserConfig,
        value: Any,
        ns_map: Optional[Dict] = None,
        default: Any = None,
        types: Optional[Sequence[Type]] = None,
        tokens_factory: Optional[Callable] = None,
        format: Optional[str] = None,
    ) -> Any:
        """Convert a value to a python primitive type.

        Args:
            meta: The xml meta instance
            var: The xml var instance
            config: The parser config instance
            value: A primitive value or a list of primitive values
            ns_map: The element namespace prefix-URI map
            default: Override the var default value
            types: Override the var types
            tokens_factory: Override the var tokens factory
            format: Override the var format

        Returns:
            The converted value or values.
        """
        try:
            value = cls.parse_value(
                value=value,
                types=types or var.types,
                default=default or var.default,
                ns_map=ns_map,
                tokens_factory=tokens_factory or var.tokens_factory,
                format=format or var.format,
            )
        except ConverterError as ex:
            message = f"Failed to convert value for `{meta.clazz.__qualname__}.{var.name}`\n  {ex}"
            if config.fail_on_converter_warnings:
                raise ParserError(message)

            warnings.warn(message, ConverterWarning)

        return value

    @classmethod
    def parse_value(
        cls,
        value: Any,
        types: Sequence[Type],
        default: Optional[Any] = None,
        ns_map: Optional[Dict] = None,
        tokens_factory: Optional[Callable] = None,
        format: Optional[str] = None,
    ) -> Any:
        """Convert a value to a python primitive type.

        Args:
            value: A primitive value or a list of primitive values
            types: An iterable of types to try to convert the value
            default: The default value/factory if the given is None
            ns_map: The element namespace prefix-URI map
            tokens_factory: A callable factory for the converted values
                if the element is derived from xs:NMTOKENS
            format: The format argument for base64/hex values or dates.

        Returns:
            The converted value or values.
        """
        if value is None:
            if callable(default):
                return default() if tokens_factory else None

            return default

        if tokens_factory:
            value = value if collections.is_array(value) else value.split()
            return tokens_factory(
                converter.deserialize(val, types, ns_map=ns_map, format=format)
                for val in value
            )

        return converter.deserialize(value, types, ns_map=ns_map, format=format)

    @classmethod
    def normalize_content(cls, value: Optional[str]) -> Optional[str]:
        """Normalize element text or tail content.

        If content is just whitespace return None, otherwise preserve
        the original content.

        Args:
            value: The element content

        Returns:
            The normalized content
        """
        if value and value.strip():
            return value

        return None

    @classmethod
    def parse_any_attributes(
        cls, attrs: Dict[str, str], ns_map: Dict[Optional[str], str]
    ) -> Dict[str, str]:
        """Parse attributes with qname support.

        Example:
            {"foo": "bar", "xsi:type": "my:type"} ->
            {"foo": "bar", "xsi:type" "{http://someuri.com}type"}

        Args:
            attrs: The element attributes
            ns_map: The element namespace prefix-URI map

        Returns:
            The parsed attributes with expanded namespace prefixes
        """
        return {
            key: cls.parse_any_attribute(value, ns_map) for key, value in attrs.items()
        }

    @classmethod
    def parse_any_attribute(cls, value: str, ns_map: Dict) -> str:
        """Expand the value with the full namespace if it has a prefix.

        Args:
            value: The attr value
            ns_map: The element namespace prefix-URI map

        Returns:
            The expanded value.
        """
        prefix, suffix = text.split(value)
        if prefix and prefix in ns_map and not suffix.startswith("//"):
            value = build_qname(ns_map[prefix], suffix)

        return value

    @classmethod
    def validate_fixed_value(cls, meta: XmlMeta, var: XmlVar, value: Any):
        """Validate if the parsed value matches the fixed value.

        Special cases
            - float nans are never equal in python
            - strings with whitespaces, need trimming

        """

        default_value = var.default() if callable(var.default) else var.default
        if (
            isinstance(default_value, float)
            and isinstance(value, float)
            and math.isnan(default_value)
            and math.isnan(value)
        ) or (
            isinstance(default_value, str)
            and isinstance(value, str)
            and default_value.strip() == value.strip()
        ):
            return

        if default_value != value:
            raise ParserError(
                f"Fixed value mismatch {meta.qname}:{var.qname}, `{default_value} != {value}`"
            )

xsi_type(attrs, ns_map) classmethod

Parse the xsi:type attribute value if present.

Parameters:

Name Type Description Default
attrs Dict

The element attributes

required
ns_map Dict

The element namespace prefix-URI map

required

Returns:

Type Description
Optional[str]

The xsi:type attribute value or None

Source code in xsdata/formats/dataclass/parsers/utils.py
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
@classmethod
def xsi_type(cls, attrs: Dict, ns_map: Dict) -> Optional[str]:
    """Parse the xsi:type attribute value if present.

    Args:
        attrs: The element attributes
        ns_map: The element namespace prefix-URI map

    Returns:
        The xsi:type attribute value or None
    """
    xsi_type = attrs.get(QNames.XSI_TYPE)
    if not xsi_type:
        return None

    namespace, name = QNameConverter.resolve(xsi_type, ns_map)
    return build_qname(namespace, name)

xsi_nil(attrs) classmethod

Return whether xsi:nil attribute value.

Parameters:

Name Type Description Default
attrs Dict

The element attributes

required

Returns:

Type Description
Optional[bool]

The bool value or None if it doesn't exist.

Source code in xsdata/formats/dataclass/parsers/utils.py
69
70
71
72
73
74
75
76
77
78
79
80
@classmethod
def xsi_nil(cls, attrs: Dict) -> Optional[bool]:
    """Return whether xsi:nil attribute value.

    Args:
        attrs: The element attributes

    Returns:
        The bool value or None if it doesn't exist.
    """
    xsi_nil = attrs.get(QNames.XSI_NIL)
    return xsi_nil == constants.XML_TRUE if xsi_nil else None

parse_var(meta, var, config, value, ns_map=None, default=None, types=None, tokens_factory=None, format=None) classmethod

Convert a value to a python primitive type.

Parameters:

Name Type Description Default
meta XmlMeta

The xml meta instance

required
var XmlVar

The xml var instance

required
config ParserConfig

The parser config instance

required
value Any

A primitive value or a list of primitive values

required
ns_map Optional[Dict]

The element namespace prefix-URI map

None
default Any

Override the var default value

None
types Optional[Sequence[Type]]

Override the var types

None
tokens_factory Optional[Callable]

Override the var tokens factory

None
format Optional[str]

Override the var format

None

Returns:

Type Description
Any

The converted value or values.

Source code in xsdata/formats/dataclass/parsers/utils.py
 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
@classmethod
def parse_var(
    cls,
    meta: XmlMeta,
    var: XmlVar,
    config: ParserConfig,
    value: Any,
    ns_map: Optional[Dict] = None,
    default: Any = None,
    types: Optional[Sequence[Type]] = None,
    tokens_factory: Optional[Callable] = None,
    format: Optional[str] = None,
) -> Any:
    """Convert a value to a python primitive type.

    Args:
        meta: The xml meta instance
        var: The xml var instance
        config: The parser config instance
        value: A primitive value or a list of primitive values
        ns_map: The element namespace prefix-URI map
        default: Override the var default value
        types: Override the var types
        tokens_factory: Override the var tokens factory
        format: Override the var format

    Returns:
        The converted value or values.
    """
    try:
        value = cls.parse_value(
            value=value,
            types=types or var.types,
            default=default or var.default,
            ns_map=ns_map,
            tokens_factory=tokens_factory or var.tokens_factory,
            format=format or var.format,
        )
    except ConverterError as ex:
        message = f"Failed to convert value for `{meta.clazz.__qualname__}.{var.name}`\n  {ex}"
        if config.fail_on_converter_warnings:
            raise ParserError(message)

        warnings.warn(message, ConverterWarning)

    return value

parse_value(value, types, default=None, ns_map=None, tokens_factory=None, format=None) classmethod

Convert a value to a python primitive type.

Parameters:

Name Type Description Default
value Any

A primitive value or a list of primitive values

required
types Sequence[Type]

An iterable of types to try to convert the value

required
default Optional[Any]

The default value/factory if the given is None

None
ns_map Optional[Dict]

The element namespace prefix-URI map

None
tokens_factory Optional[Callable]

A callable factory for the converted values if the element is derived from xs:NMTOKENS

None
format Optional[str]

The format argument for base64/hex values or dates.

None

Returns:

Type Description
Any

The converted value or values.

Source code in xsdata/formats/dataclass/parsers/utils.py
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
@classmethod
def parse_value(
    cls,
    value: Any,
    types: Sequence[Type],
    default: Optional[Any] = None,
    ns_map: Optional[Dict] = None,
    tokens_factory: Optional[Callable] = None,
    format: Optional[str] = None,
) -> Any:
    """Convert a value to a python primitive type.

    Args:
        value: A primitive value or a list of primitive values
        types: An iterable of types to try to convert the value
        default: The default value/factory if the given is None
        ns_map: The element namespace prefix-URI map
        tokens_factory: A callable factory for the converted values
            if the element is derived from xs:NMTOKENS
        format: The format argument for base64/hex values or dates.

    Returns:
        The converted value or values.
    """
    if value is None:
        if callable(default):
            return default() if tokens_factory else None

        return default

    if tokens_factory:
        value = value if collections.is_array(value) else value.split()
        return tokens_factory(
            converter.deserialize(val, types, ns_map=ns_map, format=format)
            for val in value
        )

    return converter.deserialize(value, types, ns_map=ns_map, format=format)

normalize_content(value) classmethod

Normalize element text or tail content.

If content is just whitespace return None, otherwise preserve the original content.

Parameters:

Name Type Description Default
value Optional[str]

The element content

required

Returns:

Type Description
Optional[str]

The normalized content

Source code in xsdata/formats/dataclass/parsers/utils.py
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
@classmethod
def normalize_content(cls, value: Optional[str]) -> Optional[str]:
    """Normalize element text or tail content.

    If content is just whitespace return None, otherwise preserve
    the original content.

    Args:
        value: The element content

    Returns:
        The normalized content
    """
    if value and value.strip():
        return value

    return None

parse_any_attributes(attrs, ns_map) classmethod

Parse attributes with qname support.

Example

{"foo": "bar", "xsi:type": "my:type"} -> {"foo": "bar", "xsi:type" "{http://someuri.com}type"}

Parameters:

Name Type Description Default
attrs Dict[str, str]

The element attributes

required
ns_map Dict[Optional[str], str]

The element namespace prefix-URI map

required

Returns:

Type Description
Dict[str, str]

The parsed attributes with expanded namespace prefixes

Source code in xsdata/formats/dataclass/parsers/utils.py
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
@classmethod
def parse_any_attributes(
    cls, attrs: Dict[str, str], ns_map: Dict[Optional[str], str]
) -> Dict[str, str]:
    """Parse attributes with qname support.

    Example:
        {"foo": "bar", "xsi:type": "my:type"} ->
        {"foo": "bar", "xsi:type" "{http://someuri.com}type"}

    Args:
        attrs: The element attributes
        ns_map: The element namespace prefix-URI map

    Returns:
        The parsed attributes with expanded namespace prefixes
    """
    return {
        key: cls.parse_any_attribute(value, ns_map) for key, value in attrs.items()
    }

parse_any_attribute(value, ns_map) classmethod

Expand the value with the full namespace if it has a prefix.

Parameters:

Name Type Description Default
value str

The attr value

required
ns_map Dict

The element namespace prefix-URI map

required

Returns:

Type Description
str

The expanded value.

Source code in xsdata/formats/dataclass/parsers/utils.py
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
@classmethod
def parse_any_attribute(cls, value: str, ns_map: Dict) -> str:
    """Expand the value with the full namespace if it has a prefix.

    Args:
        value: The attr value
        ns_map: The element namespace prefix-URI map

    Returns:
        The expanded value.
    """
    prefix, suffix = text.split(value)
    if prefix and prefix in ns_map and not suffix.startswith("//"):
        value = build_qname(ns_map[prefix], suffix)

    return value

validate_fixed_value(meta, var, value) classmethod

Validate if the parsed value matches the fixed value.

Special cases - float nans are never equal in python - strings with whitespaces, need trimming

Source code in xsdata/formats/dataclass/parsers/utils.py
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
@classmethod
def validate_fixed_value(cls, meta: XmlMeta, var: XmlVar, value: Any):
    """Validate if the parsed value matches the fixed value.

    Special cases
        - float nans are never equal in python
        - strings with whitespaces, need trimming

    """

    default_value = var.default() if callable(var.default) else var.default
    if (
        isinstance(default_value, float)
        and isinstance(value, float)
        and math.isnan(default_value)
        and math.isnan(value)
    ) or (
        isinstance(default_value, str)
        and isinstance(value, str)
        and default_value.strip() == value.strip()
    ):
        return

    if default_value != value:
        raise ParserError(
            f"Fixed value mismatch {meta.qname}:{var.qname}, `{default_value} != {value}`"
        )