Skip to content

bases

xsdata.formats.dataclass.parsers.bases

NodeParser dataclass

Bases: PushParser

Bind xml nodes to data classes.

Parameters:

Name Type Description Default
context XmlContext

The models context instance

field(default_factory=XmlContext)
handler Type[XmlHandler]

The xml handler class

field(default=EventsHandler)

Attributes:

Name Type Description
ns_map

The parsed namespace prefix-URI map

Source code in xsdata/formats/dataclass/parsers/bases.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
 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
@dataclass
class NodeParser(PushParser):
    """Bind xml nodes to data classes.

    Args:
        context: The models context instance
        handler: The xml handler class

    Attributes:
        ns_map: The parsed namespace prefix-URI map
    """

    context: XmlContext = field(default_factory=XmlContext)
    handler: Type[XmlHandler] = field(default=EventsHandler)

    def parse(self, source: Any, clazz: Optional[Type[T]] = None) -> T:
        """Parse the input file or stream into the target class type.

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

        Args:
            source: The source file or stream object to parse
            clazz: The target class type to parse the source bytes object

        Returns:
            An instance of the specified class representing the parsed content.
        """
        handler = self.handler(clazz=clazz, parser=self)

        with warnings.catch_warnings():
            if self.config.fail_on_converter_warnings:
                warnings.filterwarnings("error", category=ConverterWarning)

            try:
                result = handler.parse(source)
            except (ConverterWarning, SyntaxError) as e:
                raise ParserError(e)

        if result is not None:
            return result

        target_class = clazz.__name__ if clazz else ""
        raise ParserError(f"Failed to create target class `{target_class}`")

    def start(
        self,
        clazz: Optional[Type],
        queue: List[XmlNode],
        objects: List[Parsed],
        qname: str,
        attrs: Dict,
        ns_map: Dict,
    ):
        """Build and queue the XmlNode for the starting element.

        Args:
            clazz: The target class type, auto locate if omitted
            queue: The XmlNode queue list
            objects: The list of all intermediate parsed objects
            qname: The element qualified name
            attrs: The element attributes
            ns_map: The element namespace prefix-URI map
        """
        from xsdata.formats.dataclass.parsers.nodes import ElementNode, WrapperNode

        try:
            item = queue[-1]
            if isinstance(item, ElementNode) and qname in item.meta.wrappers:
                child = cast(XmlNode, WrapperNode(parent=item))
            else:
                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)
            if xsi_type is None or meta.qname == qname:
                derived_factory = None
            else:
                derived_factory = self.context.class_type.derived_element

            xsi_nil = ParserUtils.xsi_nil(attrs)

            child = ElementNode(
                position=0,
                meta=meta,
                config=self.config,
                attrs=attrs,
                ns_map=ns_map,
                context=self.context,
                derived_factory=derived_factory,
                xsi_type=xsi_type if derived_factory else None,
                xsi_nil=xsi_nil,
            )

        queue.append(child)

    def end(
        self,
        queue: List[XmlNode],
        objects: List[Parsed],
        qname: str,
        text: Optional[str],
        tail: Optional[str],
    ) -> bool:
        """Parse the last xml node and bind any intermediate objects.

        Args:
            queue: The XmlNode queue list
            objects: The list of all intermediate parsed objects
            qname: The element qualified name
            text: The element text content
            tail: The element tail content

        Returns:
            Whether the binding process was successful.
        """
        item = queue.pop()
        return item.bind(qname, text, tail, objects)

parse(source, clazz=None)

Parse the input file or 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
source Any

The source file or stream object to parse

required
clazz Optional[Type[T]]

The target class type to parse the source bytes object

None

Returns:

Type Description
T

An instance of the specified class representing the parsed content.

Source code in xsdata/formats/dataclass/parsers/bases.py
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
def parse(self, source: Any, clazz: Optional[Type[T]] = None) -> T:
    """Parse the input file or stream into the target class type.

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

    Args:
        source: The source file or stream object to parse
        clazz: The target class type to parse the source bytes object

    Returns:
        An instance of the specified class representing the parsed content.
    """
    handler = self.handler(clazz=clazz, parser=self)

    with warnings.catch_warnings():
        if self.config.fail_on_converter_warnings:
            warnings.filterwarnings("error", category=ConverterWarning)

        try:
            result = handler.parse(source)
        except (ConverterWarning, SyntaxError) as e:
            raise ParserError(e)

    if result is not None:
        return result

    target_class = clazz.__name__ if clazz else ""
    raise ParserError(f"Failed to create target class `{target_class}`")

start(clazz, queue, objects, qname, attrs, ns_map)

Build and queue the XmlNode for the starting element.

Parameters:

Name Type Description Default
clazz Optional[Type]

The target class type, auto locate if omitted

required
queue List[XmlNode]

The XmlNode queue list

required
objects List[Parsed]

The list of all intermediate parsed objects

required
qname str

The element qualified name

required
attrs Dict

The element attributes

required
ns_map Dict

The element namespace prefix-URI map

required
Source code in xsdata/formats/dataclass/parsers/bases.py
 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
def start(
    self,
    clazz: Optional[Type],
    queue: List[XmlNode],
    objects: List[Parsed],
    qname: str,
    attrs: Dict,
    ns_map: Dict,
):
    """Build and queue the XmlNode for the starting element.

    Args:
        clazz: The target class type, auto locate if omitted
        queue: The XmlNode queue list
        objects: The list of all intermediate parsed objects
        qname: The element qualified name
        attrs: The element attributes
        ns_map: The element namespace prefix-URI map
    """
    from xsdata.formats.dataclass.parsers.nodes import ElementNode, WrapperNode

    try:
        item = queue[-1]
        if isinstance(item, ElementNode) and qname in item.meta.wrappers:
            child = cast(XmlNode, WrapperNode(parent=item))
        else:
            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)
        if xsi_type is None or meta.qname == qname:
            derived_factory = None
        else:
            derived_factory = self.context.class_type.derived_element

        xsi_nil = ParserUtils.xsi_nil(attrs)

        child = ElementNode(
            position=0,
            meta=meta,
            config=self.config,
            attrs=attrs,
            ns_map=ns_map,
            context=self.context,
            derived_factory=derived_factory,
            xsi_type=xsi_type if derived_factory else None,
            xsi_nil=xsi_nil,
        )

    queue.append(child)

end(queue, objects, qname, text, tail)

Parse the last xml node and bind any intermediate objects.

Parameters:

Name Type Description Default
queue List[XmlNode]

The XmlNode queue list

required
objects List[Parsed]

The list of all intermediate parsed objects

required
qname str

The element qualified name

required
text Optional[str]

The element text content

required
tail Optional[str]

The element tail content

required

Returns:

Type Description
bool

Whether the binding process was successful.

Source code in xsdata/formats/dataclass/parsers/bases.py
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
def end(
    self,
    queue: List[XmlNode],
    objects: List[Parsed],
    qname: str,
    text: Optional[str],
    tail: Optional[str],
) -> bool:
    """Parse the last xml node and bind any intermediate objects.

    Args:
        queue: The XmlNode queue list
        objects: The list of all intermediate parsed objects
        qname: The element qualified name
        text: The element text content
        tail: The element tail content

    Returns:
        Whether the binding process was successful.
    """
    item = queue.pop()
    return item.bind(qname, text, tail, objects)

RecordParser dataclass

Bases: NodeParser

Bind xml nodes to dataclasses and store the intermediate events.

Attributes:

Name Type Description
events List

The list of recorded events

Source code in xsdata/formats/dataclass/parsers/bases.py
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
@dataclass
class RecordParser(NodeParser):
    """Bind xml nodes to dataclasses and store the intermediate events.

    Attributes:
        events: The list of recorded events
    """

    events: List = field(init=False, default_factory=list)

    def start(
        self,
        clazz: Optional[Type],
        queue: List[XmlNode],
        objects: List[Parsed],
        qname: str,
        attrs: Dict,
        ns_map: Dict,
    ):
        """Build and queue the XmlNode for the starting element.

        Record the start event for later processing.

        Args:
            clazz: The target class type, auto locate if omitted
            queue: The XmlNode queue list
            objects: The list of all intermediate parsed objects
            qname: The element qualified name
            attrs: The element attributes
            ns_map: The element namespace prefix-URI map
        """
        self.events.append((EventType.START, qname, copy.deepcopy(attrs), ns_map))
        super().start(clazz, queue, objects, qname, attrs, ns_map)

    def end(
        self,
        queue: List[XmlNode],
        objects: List[Parsed],
        qname: str,
        text: Optional[str],
        tail: Optional[str],
    ) -> Any:
        """Parse the last xml node and bind any intermediate objects.

        Record the end event for later processing

        Args:
            queue: The XmlNode queue list
            objects: The list of all intermediate parsed objects
            qname: The element qualified name
            text: The element text content
            tail: The element tail content

        Returns:
            Whether the binding process was successful.
        """
        self.events.append((EventType.END, qname, text, tail))
        return super().end(queue, objects, qname, text, tail)

    def register_namespace(self, prefix: Optional[str], uri: str):
        """Register the uri prefix in the namespace registry.

        Record the start-ns event for later processing

        Args:
            prefix: Namespace prefix
            uri: Namespace uri
        """
        self.events.append((EventType.START_NS, prefix, uri))
        super().register_namespace(prefix, uri)

start(clazz, queue, objects, qname, attrs, ns_map)

Build and queue the XmlNode for the starting element.

Record the start event for later processing.

Parameters:

Name Type Description Default
clazz Optional[Type]

The target class type, auto locate if omitted

required
queue List[XmlNode]

The XmlNode queue list

required
objects List[Parsed]

The list of all intermediate parsed objects

required
qname str

The element qualified name

required
attrs Dict

The element attributes

required
ns_map Dict

The element namespace prefix-URI map

required
Source code in xsdata/formats/dataclass/parsers/bases.py
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
def start(
    self,
    clazz: Optional[Type],
    queue: List[XmlNode],
    objects: List[Parsed],
    qname: str,
    attrs: Dict,
    ns_map: Dict,
):
    """Build and queue the XmlNode for the starting element.

    Record the start event for later processing.

    Args:
        clazz: The target class type, auto locate if omitted
        queue: The XmlNode queue list
        objects: The list of all intermediate parsed objects
        qname: The element qualified name
        attrs: The element attributes
        ns_map: The element namespace prefix-URI map
    """
    self.events.append((EventType.START, qname, copy.deepcopy(attrs), ns_map))
    super().start(clazz, queue, objects, qname, attrs, ns_map)

end(queue, objects, qname, text, tail)

Parse the last xml node and bind any intermediate objects.

Record the end event for later processing

Parameters:

Name Type Description Default
queue List[XmlNode]

The XmlNode queue list

required
objects List[Parsed]

The list of all intermediate parsed objects

required
qname str

The element qualified name

required
text Optional[str]

The element text content

required
tail Optional[str]

The element tail content

required

Returns:

Type Description
Any

Whether the binding process was successful.

Source code in xsdata/formats/dataclass/parsers/bases.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
def end(
    self,
    queue: List[XmlNode],
    objects: List[Parsed],
    qname: str,
    text: Optional[str],
    tail: Optional[str],
) -> Any:
    """Parse the last xml node and bind any intermediate objects.

    Record the end event for later processing

    Args:
        queue: The XmlNode queue list
        objects: The list of all intermediate parsed objects
        qname: The element qualified name
        text: The element text content
        tail: The element tail content

    Returns:
        Whether the binding process was successful.
    """
    self.events.append((EventType.END, qname, text, tail))
    return super().end(queue, objects, qname, text, tail)

register_namespace(prefix, uri)

Register the uri prefix in the namespace registry.

Record the start-ns event for later processing

Parameters:

Name Type Description Default
prefix Optional[str]

Namespace prefix

required
uri str

Namespace uri

required
Source code in xsdata/formats/dataclass/parsers/bases.py
213
214
215
216
217
218
219
220
221
222
223
def register_namespace(self, prefix: Optional[str], uri: str):
    """Register the uri prefix in the namespace registry.

    Record the start-ns event for later processing

    Args:
        prefix: Namespace prefix
        uri: Namespace uri
    """
    self.events.append((EventType.START_NS, prefix, uri))
    super().register_namespace(prefix, uri)