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
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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
31
32
33
34
35
36
37
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
 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
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_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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
@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
61
62
63
64
65
66
67
68
69
70
71
72
@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_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
 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
@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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
@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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
@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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
@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
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
@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}`"
        )