"""
Read and write AAS models as XML.

For reading, we provide different reading functions, each handling a different kind
of input. All the reading functions operate in one pass, *i.e.*, the source is read
incrementally and the complete XML is not held in memory.

We provide the following four reading functions (where ``X`` represents the name of
the class):

1) ``X_from_iterparse`` reads from a stream of ``(event, element)`` tuples coming from
   :py:func:`xml.etree.ElementTree.iterparse` with the argument
   ``events=["start", "end"]``. If you do not trust the source, please consider
   using `defusedxml.ElementTree`_.
2) ``X_from_stream`` reads from the given text stream.
3) ``X_from_file`` reads from a file on disk.
4) ``X_from_str`` reads from the given string.

The functions ``X_from_stream``, ``X_from_file`` and ``X_from_str`` provide
an extra parameter, ``has_iterparse``, which allows you to use a parsing library
different from :py:mod:`xml.etree.ElementTree`. For example, you can pass in
`defusedxml.ElementTree`_.

.. _defusedxml.ElementTree: https://pypi.org/project/defusedxml/#defusedxml-elementtree

All XML elements are expected to live in the :py:attr:`~NAMESPACE`.

For writing, use the function :py:func:`aas_core3.xmlization.write` which
translates the instance of the model into an XML document and writes it in one pass
to the stream.

Here is an example usage how to de-serialize from a file:

.. code-block::

    import pathlib
    import xml.etree.ElementTree as ET

    import aas_core3.xmlization as aas_xmlization

    path = pathlib.Path(...)
    instance = aas_xmlization.read_extension_from_file(
        path
    )

    # Do something with the ``instance``

Here is another code example where we serialize the instance:

.. code-block::

    import pathlib

    import aas_core3.types as aas_types
    import aas_core3.xmlization as aas_xmlization

    instance = Extension(
       ... # some constructor arguments
    )

    pth = pathlib.Path(...)
    with pth.open("wt") as fid:
        aas_xmlization.write(instance, fid)
"""

# This code has been automatically generated by aas-core-codegen.
# Do NOT edit or append.


import base64
import io
import math
import os
import sys
from typing import (
    Any,
    Callable,
    Iterator,
    List,
    Mapping,
    Optional,
    Sequence,
    TextIO,
    Tuple,
    Union,
    TYPE_CHECKING,
)
import xml.etree.ElementTree

if sys.version_info >= (3, 8):
    from typing import Final, Protocol
else:
    from typing_extensions import Final, Protocol

import aas_core3.stringification as aas_stringification
import aas_core3.types as aas_types

# See: https://stackoverflow.com/questions/55076778/why-isnt-this-function-type-annotated-correctly-error-missing-type-parameters
if TYPE_CHECKING:
    PathLike = os.PathLike[Any]
else:
    PathLike = os.PathLike


#: XML namespace in which all the elements are expected to reside
NAMESPACE = "https://admin-shell.io/aas/3/0"


# region De-serialization


#: XML namespace as a prefix specially tailored for
#: :py:mod:`xml.etree.ElementTree`
_NAMESPACE_IN_CURLY_BRACKETS = f"{{{NAMESPACE}}}"


class Element(Protocol):
    """Behave like :py:meth:`xml.etree.ElementTree.Element`."""

    @property
    def attrib(self) -> Optional[Mapping[str, str]]:
        """Attributes of the element"""
        raise NotImplementedError()

    @property
    def text(self) -> Optional[str]:
        """Text content of the element"""
        raise NotImplementedError()

    @property
    def tail(self) -> Optional[str]:
        """Tail text of the element"""
        raise NotImplementedError()

    @property
    def tag(self) -> str:
        """Tag of the element; with a namespace provided as a ``{...}`` prefix"""
        raise NotImplementedError()

    def clear(self) -> None:
        """Behave like :py:meth:`xml.etree.ElementTree.Element.clear`."""
        raise NotImplementedError()


class HasIterparse(Protocol):
    """Parse an XML document incrementally."""

    # NOTE (mristin, 2022-10-26):
    # ``self`` is not used in this context, but is necessary for Mypy,
    # see: https://github.com/python/mypy/issues/5018 and
    # https://github.com/python/mypy/commit/3efbc5c5e910296a60ed5b9e0e7eb11dd912c3ed#diff-e165eb7aed9dca0a5ebd93985c8cd263a6462d36ac185f9461348dc5a1396d76R9937

    def iterparse(
        self, source: TextIO, events: Optional[Sequence[str]] = None
    ) -> Iterator[Tuple[str, Element]]:
        """Behave like :py:func:`xml.etree.ElementTree.iterparse`."""


class ElementSegment:
    """Represent an element on a path to the erroneous value."""

    #: Erroneous element
    element: Final[Element]

    def __init__(self, element: Element) -> None:
        """Initialize with the given values."""
        self.element = element

    def __str__(self) -> str:
        """
        Render the segment as a tag without the namespace.

        We deliberately omit the namespace in the tag names. If you want to actually
        query with the resulting XPath, you have to insert the namespaces manually.
        We did not know how to include the namespace in a meaningful way, as XPath
        assumes namespace prefixes to be defined *outside* of the document. At least
        the path thus rendered is informative, and you should be able to descend it
        manually.
        """
        _, has_namespace, tag_wo_ns = self.element.tag.rpartition("}")
        if not has_namespace:
            return self.element.tag
        else:
            return tag_wo_ns


class IndexSegment:
    """Represent an element in a sequence on a path to the erroneous value."""

    #: Erroneous element
    element: Final[Element]

    #: Index of the element in the sequence
    index: Final[int]

    def __init__(self, element: Element, index: int) -> None:
        """Initialize with the given values."""
        self.element = element
        self.index = index

    def __str__(self) -> str:
        """Render the segment as an element wildcard with the index."""
        return f"*[{self.index}]"


Segment = Union[ElementSegment, IndexSegment]


class Path:
    """Represent the relative path to the erroneous element."""

    def __init__(self) -> None:
        """Initialize as an empty path."""
        self._segments = []  # type: List[Segment]

    @property
    def segments(self) -> Sequence[Segment]:
        """Get the segments of the path."""
        return self._segments

    def _prepend(self, segment: Segment) -> None:
        """Insert the :paramref:`segment` in front of other segments."""
        self._segments.insert(0, segment)

    def __str__(self) -> str:
        """Render the path as a relative XPath.

        We omit the leading ``/`` so that you can easily prefix it as you need.
        """
        return "/".join(str(segment) for segment in self._segments)


class DeserializationException(Exception):
    """Signal that the XML de-serialization could not be performed."""

    #: Human-readable explanation of the exception's cause
    cause: Final[str]

    #: Relative path to the erroneous value
    path: Final[Path]

    def __init__(self, cause: str) -> None:
        """Initialize with the given :paramref:`cause` and an empty path."""
        self.cause = cause
        self.path = Path()


def _with_elements_cleared_after_yield(
    iterator: Iterator[Tuple[str, Element]],
) -> Iterator[Tuple[str, Element]]:
    """
    Map the :paramref:`iterator` such that the element is ``clear()``'ed
    *after* every ``yield``.

    :param iterator: to be mapped
    :yield: event and element from :paramref:`iterator`
    """
    for event, element in iterator:
        yield event, element
        element.clear()


def has_semantics_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.HasSemantics:
    """
    Read an instance of :py:class:`.types.HasSemantics` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.has_semantics_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.HasSemantics` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for HasSemantics, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for HasSemantics, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_has_semantics_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def has_semantics_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.HasSemantics:
    """
    Read an instance of :py:class:`.types.HasSemantics` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.has_semantics_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.HasSemantics` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.HasSemantics` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return has_semantics_from_iterparse(_with_elements_cleared_after_yield(iterator))


def has_semantics_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.HasSemantics:
    """
    Read an instance of :py:class:`.types.HasSemantics` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.has_semantics_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.HasSemantics` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.HasSemantics` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return has_semantics_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def has_semantics_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.HasSemantics:
    """
    Read an instance of :py:class:`.types.HasSemantics` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.has_semantics_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.HasSemantics` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.HasSemantics` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return has_semantics_from_iterparse(_with_elements_cleared_after_yield(iterator))


def extension_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.Extension:
    """
    Read an instance of :py:class:`.types.Extension` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.extension_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Extension` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for Extension, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for Extension, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_extension_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def extension_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Extension:
    """
    Read an instance of :py:class:`.types.Extension` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.extension_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.Extension` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Extension` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return extension_from_iterparse(_with_elements_cleared_after_yield(iterator))


def extension_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Extension:
    """
    Read an instance of :py:class:`.types.Extension` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.extension_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.Extension` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Extension` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return extension_from_iterparse(_with_elements_cleared_after_yield(iterator))


def extension_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Extension:
    """
    Read an instance of :py:class:`.types.Extension` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.extension_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.Extension` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Extension` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return extension_from_iterparse(_with_elements_cleared_after_yield(iterator))


def has_extensions_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.HasExtensions:
    """
    Read an instance of :py:class:`.types.HasExtensions` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.has_extensions_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.HasExtensions` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for HasExtensions, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for HasExtensions, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_has_extensions_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def has_extensions_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.HasExtensions:
    """
    Read an instance of :py:class:`.types.HasExtensions` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.has_extensions_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.HasExtensions` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.HasExtensions` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return has_extensions_from_iterparse(_with_elements_cleared_after_yield(iterator))


def has_extensions_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.HasExtensions:
    """
    Read an instance of :py:class:`.types.HasExtensions` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.has_extensions_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.HasExtensions` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.HasExtensions` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return has_extensions_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def has_extensions_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.HasExtensions:
    """
    Read an instance of :py:class:`.types.HasExtensions` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.has_extensions_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.HasExtensions` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.HasExtensions` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return has_extensions_from_iterparse(_with_elements_cleared_after_yield(iterator))


def referable_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.Referable:
    """
    Read an instance of :py:class:`.types.Referable` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.referable_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Referable` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for Referable, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for Referable, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_referable_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def referable_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Referable:
    """
    Read an instance of :py:class:`.types.Referable` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.referable_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.Referable` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Referable` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return referable_from_iterparse(_with_elements_cleared_after_yield(iterator))


def referable_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Referable:
    """
    Read an instance of :py:class:`.types.Referable` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.referable_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.Referable` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Referable` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return referable_from_iterparse(_with_elements_cleared_after_yield(iterator))


def referable_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Referable:
    """
    Read an instance of :py:class:`.types.Referable` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.referable_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.Referable` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Referable` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return referable_from_iterparse(_with_elements_cleared_after_yield(iterator))


def identifiable_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.Identifiable:
    """
    Read an instance of :py:class:`.types.Identifiable` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.identifiable_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Identifiable` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for Identifiable, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for Identifiable, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_identifiable_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def identifiable_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Identifiable:
    """
    Read an instance of :py:class:`.types.Identifiable` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.identifiable_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.Identifiable` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Identifiable` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return identifiable_from_iterparse(_with_elements_cleared_after_yield(iterator))


def identifiable_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Identifiable:
    """
    Read an instance of :py:class:`.types.Identifiable` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.identifiable_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.Identifiable` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Identifiable` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return identifiable_from_iterparse(_with_elements_cleared_after_yield(iterator))


def identifiable_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Identifiable:
    """
    Read an instance of :py:class:`.types.Identifiable` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.identifiable_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.Identifiable` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Identifiable` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return identifiable_from_iterparse(_with_elements_cleared_after_yield(iterator))


def has_kind_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.HasKind:
    """
    Read an instance of :py:class:`.types.HasKind` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.has_kind_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.HasKind` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for HasKind, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for HasKind, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_has_kind_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def has_kind_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.HasKind:
    """
    Read an instance of :py:class:`.types.HasKind` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.has_kind_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.HasKind` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.HasKind` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return has_kind_from_iterparse(_with_elements_cleared_after_yield(iterator))


def has_kind_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.HasKind:
    """
    Read an instance of :py:class:`.types.HasKind` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.has_kind_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.HasKind` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.HasKind` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return has_kind_from_iterparse(_with_elements_cleared_after_yield(iterator))


def has_kind_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.HasKind:
    """
    Read an instance of :py:class:`.types.HasKind` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.has_kind_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.HasKind` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.HasKind` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return has_kind_from_iterparse(_with_elements_cleared_after_yield(iterator))


def has_data_specification_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.HasDataSpecification:
    """
    Read an instance of :py:class:`.types.HasDataSpecification` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.has_data_specification_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.HasDataSpecification` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for HasDataSpecification, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for HasDataSpecification, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_has_data_specification_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def has_data_specification_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.HasDataSpecification:
    """
    Read an instance of :py:class:`.types.HasDataSpecification` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.has_data_specification_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.HasDataSpecification` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.HasDataSpecification` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return has_data_specification_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def has_data_specification_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.HasDataSpecification:
    """
    Read an instance of :py:class:`.types.HasDataSpecification` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.has_data_specification_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.HasDataSpecification` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.HasDataSpecification` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return has_data_specification_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def has_data_specification_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.HasDataSpecification:
    """
    Read an instance of :py:class:`.types.HasDataSpecification` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.has_data_specification_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.HasDataSpecification` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.HasDataSpecification` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return has_data_specification_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def administrative_information_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.AdministrativeInformation:
    """
    Read an instance of :py:class:`.types.AdministrativeInformation` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.administrative_information_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AdministrativeInformation` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for AdministrativeInformation, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for AdministrativeInformation, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_administrative_information_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def administrative_information_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.AdministrativeInformation:
    """
    Read an instance of :py:class:`.types.AdministrativeInformation` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.administrative_information_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.AdministrativeInformation` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AdministrativeInformation` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return administrative_information_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def administrative_information_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.AdministrativeInformation:
    """
    Read an instance of :py:class:`.types.AdministrativeInformation` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.administrative_information_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.AdministrativeInformation` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AdministrativeInformation` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return administrative_information_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def administrative_information_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.AdministrativeInformation:
    """
    Read an instance of :py:class:`.types.AdministrativeInformation` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.administrative_information_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.AdministrativeInformation` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AdministrativeInformation` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return administrative_information_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def qualifiable_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.Qualifiable:
    """
    Read an instance of :py:class:`.types.Qualifiable` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.qualifiable_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Qualifiable` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for Qualifiable, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for Qualifiable, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_qualifiable_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def qualifiable_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Qualifiable:
    """
    Read an instance of :py:class:`.types.Qualifiable` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.qualifiable_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.Qualifiable` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Qualifiable` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return qualifiable_from_iterparse(_with_elements_cleared_after_yield(iterator))


def qualifiable_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Qualifiable:
    """
    Read an instance of :py:class:`.types.Qualifiable` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.qualifiable_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.Qualifiable` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Qualifiable` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return qualifiable_from_iterparse(_with_elements_cleared_after_yield(iterator))


def qualifiable_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Qualifiable:
    """
    Read an instance of :py:class:`.types.Qualifiable` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.qualifiable_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.Qualifiable` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Qualifiable` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return qualifiable_from_iterparse(_with_elements_cleared_after_yield(iterator))


def qualifier_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.Qualifier:
    """
    Read an instance of :py:class:`.types.Qualifier` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.qualifier_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Qualifier` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for Qualifier, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for Qualifier, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_qualifier_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def qualifier_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Qualifier:
    """
    Read an instance of :py:class:`.types.Qualifier` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.qualifier_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.Qualifier` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Qualifier` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return qualifier_from_iterparse(_with_elements_cleared_after_yield(iterator))


def qualifier_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Qualifier:
    """
    Read an instance of :py:class:`.types.Qualifier` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.qualifier_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.Qualifier` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Qualifier` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return qualifier_from_iterparse(_with_elements_cleared_after_yield(iterator))


def qualifier_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Qualifier:
    """
    Read an instance of :py:class:`.types.Qualifier` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.qualifier_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.Qualifier` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Qualifier` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return qualifier_from_iterparse(_with_elements_cleared_after_yield(iterator))


def asset_administration_shell_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.AssetAdministrationShell:
    """
    Read an instance of :py:class:`.types.AssetAdministrationShell` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.asset_administration_shell_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AssetAdministrationShell` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for AssetAdministrationShell, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for AssetAdministrationShell, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_asset_administration_shell_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def asset_administration_shell_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.AssetAdministrationShell:
    """
    Read an instance of :py:class:`.types.AssetAdministrationShell` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.asset_administration_shell_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.AssetAdministrationShell` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AssetAdministrationShell` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return asset_administration_shell_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def asset_administration_shell_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.AssetAdministrationShell:
    """
    Read an instance of :py:class:`.types.AssetAdministrationShell` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.asset_administration_shell_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.AssetAdministrationShell` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AssetAdministrationShell` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return asset_administration_shell_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def asset_administration_shell_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.AssetAdministrationShell:
    """
    Read an instance of :py:class:`.types.AssetAdministrationShell` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.asset_administration_shell_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.AssetAdministrationShell` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AssetAdministrationShell` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return asset_administration_shell_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def asset_information_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.AssetInformation:
    """
    Read an instance of :py:class:`.types.AssetInformation` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.asset_information_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AssetInformation` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for AssetInformation, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for AssetInformation, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_asset_information_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def asset_information_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.AssetInformation:
    """
    Read an instance of :py:class:`.types.AssetInformation` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.asset_information_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.AssetInformation` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AssetInformation` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return asset_information_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def asset_information_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.AssetInformation:
    """
    Read an instance of :py:class:`.types.AssetInformation` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.asset_information_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.AssetInformation` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AssetInformation` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return asset_information_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def asset_information_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.AssetInformation:
    """
    Read an instance of :py:class:`.types.AssetInformation` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.asset_information_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.AssetInformation` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AssetInformation` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return asset_information_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def resource_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.Resource:
    """
    Read an instance of :py:class:`.types.Resource` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.resource_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Resource` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for Resource, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for Resource, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_resource_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def resource_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Resource:
    """
    Read an instance of :py:class:`.types.Resource` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.resource_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.Resource` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Resource` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return resource_from_iterparse(_with_elements_cleared_after_yield(iterator))


def resource_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Resource:
    """
    Read an instance of :py:class:`.types.Resource` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.resource_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.Resource` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Resource` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return resource_from_iterparse(_with_elements_cleared_after_yield(iterator))


def resource_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Resource:
    """
    Read an instance of :py:class:`.types.Resource` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.resource_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.Resource` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Resource` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return resource_from_iterparse(_with_elements_cleared_after_yield(iterator))


def specific_asset_id_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.SpecificAssetID:
    """
    Read an instance of :py:class:`.types.SpecificAssetID` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.specific_asset_id_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.SpecificAssetID` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for SpecificAssetID, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for SpecificAssetID, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_specific_asset_id_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def specific_asset_id_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.SpecificAssetID:
    """
    Read an instance of :py:class:`.types.SpecificAssetID` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.specific_asset_id_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.SpecificAssetID` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.SpecificAssetID` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return specific_asset_id_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def specific_asset_id_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.SpecificAssetID:
    """
    Read an instance of :py:class:`.types.SpecificAssetID` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.specific_asset_id_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.SpecificAssetID` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.SpecificAssetID` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return specific_asset_id_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def specific_asset_id_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.SpecificAssetID:
    """
    Read an instance of :py:class:`.types.SpecificAssetID` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.specific_asset_id_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.SpecificAssetID` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.SpecificAssetID` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return specific_asset_id_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def submodel_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.Submodel:
    """
    Read an instance of :py:class:`.types.Submodel` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.submodel_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Submodel` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for Submodel, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for Submodel, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_submodel_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def submodel_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Submodel:
    """
    Read an instance of :py:class:`.types.Submodel` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.submodel_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.Submodel` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Submodel` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return submodel_from_iterparse(_with_elements_cleared_after_yield(iterator))


def submodel_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Submodel:
    """
    Read an instance of :py:class:`.types.Submodel` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.submodel_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.Submodel` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Submodel` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return submodel_from_iterparse(_with_elements_cleared_after_yield(iterator))


def submodel_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Submodel:
    """
    Read an instance of :py:class:`.types.Submodel` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.submodel_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.Submodel` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Submodel` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return submodel_from_iterparse(_with_elements_cleared_after_yield(iterator))


def submodel_element_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.SubmodelElement:
    """
    Read an instance of :py:class:`.types.SubmodelElement` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.submodel_element_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.SubmodelElement` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for SubmodelElement, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for SubmodelElement, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_submodel_element_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def submodel_element_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.SubmodelElement:
    """
    Read an instance of :py:class:`.types.SubmodelElement` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.submodel_element_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.SubmodelElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.SubmodelElement` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return submodel_element_from_iterparse(_with_elements_cleared_after_yield(iterator))


def submodel_element_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.SubmodelElement:
    """
    Read an instance of :py:class:`.types.SubmodelElement` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.submodel_element_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.SubmodelElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.SubmodelElement` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return submodel_element_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def submodel_element_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.SubmodelElement:
    """
    Read an instance of :py:class:`.types.SubmodelElement` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.submodel_element_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.SubmodelElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.SubmodelElement` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return submodel_element_from_iterparse(_with_elements_cleared_after_yield(iterator))


def relationship_element_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.RelationshipElement:
    """
    Read an instance of :py:class:`.types.RelationshipElement` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.relationship_element_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.RelationshipElement` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for RelationshipElement, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for RelationshipElement, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_relationship_element_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def relationship_element_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.RelationshipElement:
    """
    Read an instance of :py:class:`.types.RelationshipElement` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.relationship_element_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.RelationshipElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.RelationshipElement` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return relationship_element_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def relationship_element_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.RelationshipElement:
    """
    Read an instance of :py:class:`.types.RelationshipElement` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.relationship_element_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.RelationshipElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.RelationshipElement` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return relationship_element_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def relationship_element_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.RelationshipElement:
    """
    Read an instance of :py:class:`.types.RelationshipElement` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.relationship_element_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.RelationshipElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.RelationshipElement` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return relationship_element_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def submodel_element_list_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.SubmodelElementList:
    """
    Read an instance of :py:class:`.types.SubmodelElementList` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.submodel_element_list_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.SubmodelElementList` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for SubmodelElementList, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for SubmodelElementList, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_submodel_element_list_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def submodel_element_list_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.SubmodelElementList:
    """
    Read an instance of :py:class:`.types.SubmodelElementList` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.submodel_element_list_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.SubmodelElementList` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.SubmodelElementList` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return submodel_element_list_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def submodel_element_list_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.SubmodelElementList:
    """
    Read an instance of :py:class:`.types.SubmodelElementList` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.submodel_element_list_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.SubmodelElementList` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.SubmodelElementList` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return submodel_element_list_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def submodel_element_list_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.SubmodelElementList:
    """
    Read an instance of :py:class:`.types.SubmodelElementList` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.submodel_element_list_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.SubmodelElementList` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.SubmodelElementList` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return submodel_element_list_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def submodel_element_collection_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.SubmodelElementCollection:
    """
    Read an instance of :py:class:`.types.SubmodelElementCollection` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.submodel_element_collection_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.SubmodelElementCollection` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for SubmodelElementCollection, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for SubmodelElementCollection, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_submodel_element_collection_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def submodel_element_collection_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.SubmodelElementCollection:
    """
    Read an instance of :py:class:`.types.SubmodelElementCollection` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.submodel_element_collection_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.SubmodelElementCollection` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.SubmodelElementCollection` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return submodel_element_collection_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def submodel_element_collection_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.SubmodelElementCollection:
    """
    Read an instance of :py:class:`.types.SubmodelElementCollection` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.submodel_element_collection_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.SubmodelElementCollection` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.SubmodelElementCollection` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return submodel_element_collection_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def submodel_element_collection_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.SubmodelElementCollection:
    """
    Read an instance of :py:class:`.types.SubmodelElementCollection` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.submodel_element_collection_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.SubmodelElementCollection` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.SubmodelElementCollection` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return submodel_element_collection_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def data_element_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.DataElement:
    """
    Read an instance of :py:class:`.types.DataElement` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.data_element_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.DataElement` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for DataElement, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for DataElement, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_data_element_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def data_element_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.DataElement:
    """
    Read an instance of :py:class:`.types.DataElement` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.data_element_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.DataElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.DataElement` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return data_element_from_iterparse(_with_elements_cleared_after_yield(iterator))


def data_element_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.DataElement:
    """
    Read an instance of :py:class:`.types.DataElement` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.data_element_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.DataElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.DataElement` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return data_element_from_iterparse(_with_elements_cleared_after_yield(iterator))


def data_element_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.DataElement:
    """
    Read an instance of :py:class:`.types.DataElement` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.data_element_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.DataElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.DataElement` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return data_element_from_iterparse(_with_elements_cleared_after_yield(iterator))


def property_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.Property:
    """
    Read an instance of :py:class:`.types.Property` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.property_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Property` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for Property, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for Property, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_property_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def property_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Property:
    """
    Read an instance of :py:class:`.types.Property` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.property_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.Property` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Property` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return property_from_iterparse(_with_elements_cleared_after_yield(iterator))


def property_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Property:
    """
    Read an instance of :py:class:`.types.Property` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.property_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.Property` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Property` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return property_from_iterparse(_with_elements_cleared_after_yield(iterator))


def property_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Property:
    """
    Read an instance of :py:class:`.types.Property` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.property_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.Property` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Property` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return property_from_iterparse(_with_elements_cleared_after_yield(iterator))


def multi_language_property_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.MultiLanguageProperty:
    """
    Read an instance of :py:class:`.types.MultiLanguageProperty` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.multi_language_property_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.MultiLanguageProperty` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for MultiLanguageProperty, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for MultiLanguageProperty, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_multi_language_property_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def multi_language_property_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.MultiLanguageProperty:
    """
    Read an instance of :py:class:`.types.MultiLanguageProperty` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.multi_language_property_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.MultiLanguageProperty` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.MultiLanguageProperty` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return multi_language_property_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def multi_language_property_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.MultiLanguageProperty:
    """
    Read an instance of :py:class:`.types.MultiLanguageProperty` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.multi_language_property_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.MultiLanguageProperty` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.MultiLanguageProperty` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return multi_language_property_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def multi_language_property_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.MultiLanguageProperty:
    """
    Read an instance of :py:class:`.types.MultiLanguageProperty` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.multi_language_property_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.MultiLanguageProperty` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.MultiLanguageProperty` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return multi_language_property_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def range_from_iterparse(iterator: Iterator[Tuple[str, Element]]) -> aas_types.Range:
    """
    Read an instance of :py:class:`.types.Range` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.range_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Range` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for Range, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for Range, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_range_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def range_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Range:
    """
    Read an instance of :py:class:`.types.Range` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.range_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.Range` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Range` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return range_from_iterparse(_with_elements_cleared_after_yield(iterator))


def range_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Range:
    """
    Read an instance of :py:class:`.types.Range` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.range_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.Range` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Range` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return range_from_iterparse(_with_elements_cleared_after_yield(iterator))


def range_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Range:
    """
    Read an instance of :py:class:`.types.Range` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.range_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.Range` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Range` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return range_from_iterparse(_with_elements_cleared_after_yield(iterator))


def reference_element_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.ReferenceElement:
    """
    Read an instance of :py:class:`.types.ReferenceElement` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.reference_element_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.ReferenceElement` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for ReferenceElement, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for ReferenceElement, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_reference_element_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def reference_element_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.ReferenceElement:
    """
    Read an instance of :py:class:`.types.ReferenceElement` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.reference_element_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.ReferenceElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.ReferenceElement` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return reference_element_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def reference_element_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.ReferenceElement:
    """
    Read an instance of :py:class:`.types.ReferenceElement` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.reference_element_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.ReferenceElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.ReferenceElement` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return reference_element_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def reference_element_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.ReferenceElement:
    """
    Read an instance of :py:class:`.types.ReferenceElement` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.reference_element_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.ReferenceElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.ReferenceElement` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return reference_element_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def blob_from_iterparse(iterator: Iterator[Tuple[str, Element]]) -> aas_types.Blob:
    """
    Read an instance of :py:class:`.types.Blob` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.blob_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Blob` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for Blob, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for Blob, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_blob_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def blob_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Blob:
    """
    Read an instance of :py:class:`.types.Blob` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.blob_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.Blob` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Blob` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return blob_from_iterparse(_with_elements_cleared_after_yield(iterator))


def blob_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Blob:
    """
    Read an instance of :py:class:`.types.Blob` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.blob_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.Blob` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Blob` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return blob_from_iterparse(_with_elements_cleared_after_yield(iterator))


def blob_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Blob:
    """
    Read an instance of :py:class:`.types.Blob` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.blob_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.Blob` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Blob` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return blob_from_iterparse(_with_elements_cleared_after_yield(iterator))


def file_from_iterparse(iterator: Iterator[Tuple[str, Element]]) -> aas_types.File:
    """
    Read an instance of :py:class:`.types.File` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.file_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.File` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for File, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for File, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_file_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def file_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.File:
    """
    Read an instance of :py:class:`.types.File` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.file_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.File` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.File` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return file_from_iterparse(_with_elements_cleared_after_yield(iterator))


def file_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.File:
    """
    Read an instance of :py:class:`.types.File` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.file_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.File` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.File` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return file_from_iterparse(_with_elements_cleared_after_yield(iterator))


def file_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.File:
    """
    Read an instance of :py:class:`.types.File` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.file_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.File` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.File` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return file_from_iterparse(_with_elements_cleared_after_yield(iterator))


def annotated_relationship_element_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.AnnotatedRelationshipElement:
    """
    Read an instance of :py:class:`.types.AnnotatedRelationshipElement` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.annotated_relationship_element_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AnnotatedRelationshipElement` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for AnnotatedRelationshipElement, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for AnnotatedRelationshipElement, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_annotated_relationship_element_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def annotated_relationship_element_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.AnnotatedRelationshipElement:
    """
    Read an instance of :py:class:`.types.AnnotatedRelationshipElement` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.annotated_relationship_element_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.AnnotatedRelationshipElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AnnotatedRelationshipElement` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return annotated_relationship_element_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def annotated_relationship_element_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.AnnotatedRelationshipElement:
    """
    Read an instance of :py:class:`.types.AnnotatedRelationshipElement` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.annotated_relationship_element_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.AnnotatedRelationshipElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AnnotatedRelationshipElement` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return annotated_relationship_element_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def annotated_relationship_element_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.AnnotatedRelationshipElement:
    """
    Read an instance of :py:class:`.types.AnnotatedRelationshipElement` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.annotated_relationship_element_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.AnnotatedRelationshipElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AnnotatedRelationshipElement` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return annotated_relationship_element_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def entity_from_iterparse(iterator: Iterator[Tuple[str, Element]]) -> aas_types.Entity:
    """
    Read an instance of :py:class:`.types.Entity` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.entity_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Entity` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for Entity, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for Entity, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_entity_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def entity_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Entity:
    """
    Read an instance of :py:class:`.types.Entity` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.entity_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.Entity` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Entity` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return entity_from_iterparse(_with_elements_cleared_after_yield(iterator))


def entity_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Entity:
    """
    Read an instance of :py:class:`.types.Entity` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.entity_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.Entity` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Entity` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return entity_from_iterparse(_with_elements_cleared_after_yield(iterator))


def entity_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Entity:
    """
    Read an instance of :py:class:`.types.Entity` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.entity_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.Entity` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Entity` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return entity_from_iterparse(_with_elements_cleared_after_yield(iterator))


def event_payload_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.EventPayload:
    """
    Read an instance of :py:class:`.types.EventPayload` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.event_payload_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.EventPayload` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for EventPayload, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for EventPayload, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_event_payload_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def event_payload_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.EventPayload:
    """
    Read an instance of :py:class:`.types.EventPayload` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.event_payload_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.EventPayload` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.EventPayload` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return event_payload_from_iterparse(_with_elements_cleared_after_yield(iterator))


def event_payload_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.EventPayload:
    """
    Read an instance of :py:class:`.types.EventPayload` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.event_payload_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.EventPayload` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.EventPayload` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return event_payload_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def event_payload_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.EventPayload:
    """
    Read an instance of :py:class:`.types.EventPayload` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.event_payload_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.EventPayload` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.EventPayload` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return event_payload_from_iterparse(_with_elements_cleared_after_yield(iterator))


def event_element_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.EventElement:
    """
    Read an instance of :py:class:`.types.EventElement` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.event_element_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.EventElement` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for EventElement, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for EventElement, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_event_element_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def event_element_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.EventElement:
    """
    Read an instance of :py:class:`.types.EventElement` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.event_element_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.EventElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.EventElement` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return event_element_from_iterparse(_with_elements_cleared_after_yield(iterator))


def event_element_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.EventElement:
    """
    Read an instance of :py:class:`.types.EventElement` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.event_element_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.EventElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.EventElement` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return event_element_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def event_element_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.EventElement:
    """
    Read an instance of :py:class:`.types.EventElement` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.event_element_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.EventElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.EventElement` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return event_element_from_iterparse(_with_elements_cleared_after_yield(iterator))


def basic_event_element_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.BasicEventElement:
    """
    Read an instance of :py:class:`.types.BasicEventElement` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.basic_event_element_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.BasicEventElement` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for BasicEventElement, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for BasicEventElement, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_basic_event_element_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def basic_event_element_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.BasicEventElement:
    """
    Read an instance of :py:class:`.types.BasicEventElement` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.basic_event_element_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.BasicEventElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.BasicEventElement` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return basic_event_element_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def basic_event_element_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.BasicEventElement:
    """
    Read an instance of :py:class:`.types.BasicEventElement` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.basic_event_element_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.BasicEventElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.BasicEventElement` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return basic_event_element_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def basic_event_element_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.BasicEventElement:
    """
    Read an instance of :py:class:`.types.BasicEventElement` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.basic_event_element_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.BasicEventElement` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.BasicEventElement` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return basic_event_element_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def operation_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.Operation:
    """
    Read an instance of :py:class:`.types.Operation` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.operation_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Operation` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for Operation, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for Operation, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_operation_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def operation_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Operation:
    """
    Read an instance of :py:class:`.types.Operation` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.operation_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.Operation` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Operation` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return operation_from_iterparse(_with_elements_cleared_after_yield(iterator))


def operation_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Operation:
    """
    Read an instance of :py:class:`.types.Operation` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.operation_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.Operation` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Operation` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return operation_from_iterparse(_with_elements_cleared_after_yield(iterator))


def operation_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Operation:
    """
    Read an instance of :py:class:`.types.Operation` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.operation_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.Operation` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Operation` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return operation_from_iterparse(_with_elements_cleared_after_yield(iterator))


def operation_variable_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.OperationVariable:
    """
    Read an instance of :py:class:`.types.OperationVariable` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.operation_variable_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.OperationVariable` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for OperationVariable, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for OperationVariable, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_operation_variable_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def operation_variable_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.OperationVariable:
    """
    Read an instance of :py:class:`.types.OperationVariable` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.operation_variable_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.OperationVariable` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.OperationVariable` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return operation_variable_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def operation_variable_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.OperationVariable:
    """
    Read an instance of :py:class:`.types.OperationVariable` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.operation_variable_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.OperationVariable` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.OperationVariable` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return operation_variable_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def operation_variable_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.OperationVariable:
    """
    Read an instance of :py:class:`.types.OperationVariable` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.operation_variable_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.OperationVariable` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.OperationVariable` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return operation_variable_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def capability_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.Capability:
    """
    Read an instance of :py:class:`.types.Capability` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.capability_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Capability` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for Capability, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for Capability, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_capability_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def capability_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Capability:
    """
    Read an instance of :py:class:`.types.Capability` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.capability_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.Capability` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Capability` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return capability_from_iterparse(_with_elements_cleared_after_yield(iterator))


def capability_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Capability:
    """
    Read an instance of :py:class:`.types.Capability` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.capability_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.Capability` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Capability` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return capability_from_iterparse(_with_elements_cleared_after_yield(iterator))


def capability_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Capability:
    """
    Read an instance of :py:class:`.types.Capability` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.capability_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.Capability` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Capability` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return capability_from_iterparse(_with_elements_cleared_after_yield(iterator))


def concept_description_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.ConceptDescription:
    """
    Read an instance of :py:class:`.types.ConceptDescription` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.concept_description_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.ConceptDescription` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for ConceptDescription, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for ConceptDescription, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_concept_description_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def concept_description_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.ConceptDescription:
    """
    Read an instance of :py:class:`.types.ConceptDescription` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.concept_description_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.ConceptDescription` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.ConceptDescription` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return concept_description_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def concept_description_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.ConceptDescription:
    """
    Read an instance of :py:class:`.types.ConceptDescription` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.concept_description_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.ConceptDescription` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.ConceptDescription` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return concept_description_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def concept_description_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.ConceptDescription:
    """
    Read an instance of :py:class:`.types.ConceptDescription` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.concept_description_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.ConceptDescription` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.ConceptDescription` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return concept_description_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def reference_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.Reference:
    """
    Read an instance of :py:class:`.types.Reference` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.reference_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Reference` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for Reference, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for Reference, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_reference_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def reference_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Reference:
    """
    Read an instance of :py:class:`.types.Reference` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.reference_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.Reference` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Reference` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return reference_from_iterparse(_with_elements_cleared_after_yield(iterator))


def reference_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Reference:
    """
    Read an instance of :py:class:`.types.Reference` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.reference_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.Reference` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Reference` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return reference_from_iterparse(_with_elements_cleared_after_yield(iterator))


def reference_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Reference:
    """
    Read an instance of :py:class:`.types.Reference` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.reference_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.Reference` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Reference` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return reference_from_iterparse(_with_elements_cleared_after_yield(iterator))


def key_from_iterparse(iterator: Iterator[Tuple[str, Element]]) -> aas_types.Key:
    """
    Read an instance of :py:class:`.types.Key` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.key_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Key` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for Key, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for Key, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_key_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def key_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Key:
    """
    Read an instance of :py:class:`.types.Key` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.key_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.Key` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Key` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return key_from_iterparse(_with_elements_cleared_after_yield(iterator))


def key_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Key:
    """
    Read an instance of :py:class:`.types.Key` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.key_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.Key` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Key` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return key_from_iterparse(_with_elements_cleared_after_yield(iterator))


def key_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Key:
    """
    Read an instance of :py:class:`.types.Key` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.key_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.Key` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Key` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return key_from_iterparse(_with_elements_cleared_after_yield(iterator))


def abstract_lang_string_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.AbstractLangString:
    """
    Read an instance of :py:class:`.types.AbstractLangString` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.abstract_lang_string_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AbstractLangString` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for AbstractLangString, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for AbstractLangString, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_abstract_lang_string_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def abstract_lang_string_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.AbstractLangString:
    """
    Read an instance of :py:class:`.types.AbstractLangString` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.abstract_lang_string_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.AbstractLangString` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AbstractLangString` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return abstract_lang_string_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def abstract_lang_string_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.AbstractLangString:
    """
    Read an instance of :py:class:`.types.AbstractLangString` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.abstract_lang_string_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.AbstractLangString` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AbstractLangString` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return abstract_lang_string_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def abstract_lang_string_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.AbstractLangString:
    """
    Read an instance of :py:class:`.types.AbstractLangString` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.abstract_lang_string_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.AbstractLangString` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.AbstractLangString` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return abstract_lang_string_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def lang_string_name_type_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.LangStringNameType:
    """
    Read an instance of :py:class:`.types.LangStringNameType` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.lang_string_name_type_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringNameType` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for LangStringNameType, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for LangStringNameType, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_lang_string_name_type_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def lang_string_name_type_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.LangStringNameType:
    """
    Read an instance of :py:class:`.types.LangStringNameType` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.lang_string_name_type_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.LangStringNameType` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringNameType` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return lang_string_name_type_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def lang_string_name_type_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.LangStringNameType:
    """
    Read an instance of :py:class:`.types.LangStringNameType` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.lang_string_name_type_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.LangStringNameType` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringNameType` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return lang_string_name_type_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def lang_string_name_type_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.LangStringNameType:
    """
    Read an instance of :py:class:`.types.LangStringNameType` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.lang_string_name_type_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.LangStringNameType` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringNameType` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return lang_string_name_type_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def lang_string_text_type_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.LangStringTextType:
    """
    Read an instance of :py:class:`.types.LangStringTextType` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.lang_string_text_type_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringTextType` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for LangStringTextType, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for LangStringTextType, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_lang_string_text_type_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def lang_string_text_type_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.LangStringTextType:
    """
    Read an instance of :py:class:`.types.LangStringTextType` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.lang_string_text_type_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.LangStringTextType` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringTextType` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return lang_string_text_type_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def lang_string_text_type_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.LangStringTextType:
    """
    Read an instance of :py:class:`.types.LangStringTextType` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.lang_string_text_type_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.LangStringTextType` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringTextType` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return lang_string_text_type_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def lang_string_text_type_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.LangStringTextType:
    """
    Read an instance of :py:class:`.types.LangStringTextType` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.lang_string_text_type_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.LangStringTextType` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringTextType` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return lang_string_text_type_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def environment_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.Environment:
    """
    Read an instance of :py:class:`.types.Environment` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.environment_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Environment` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for Environment, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for Environment, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_environment_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def environment_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Environment:
    """
    Read an instance of :py:class:`.types.Environment` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.environment_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.Environment` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Environment` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return environment_from_iterparse(_with_elements_cleared_after_yield(iterator))


def environment_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Environment:
    """
    Read an instance of :py:class:`.types.Environment` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.environment_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.Environment` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Environment` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return environment_from_iterparse(_with_elements_cleared_after_yield(iterator))


def environment_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Environment:
    """
    Read an instance of :py:class:`.types.Environment` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.environment_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.Environment` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Environment` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return environment_from_iterparse(_with_elements_cleared_after_yield(iterator))


def data_specification_content_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.DataSpecificationContent:
    """
    Read an instance of :py:class:`.types.DataSpecificationContent` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.data_specification_content_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.DataSpecificationContent` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for DataSpecificationContent, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for DataSpecificationContent, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_data_specification_content_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def data_specification_content_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.DataSpecificationContent:
    """
    Read an instance of :py:class:`.types.DataSpecificationContent` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.data_specification_content_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.DataSpecificationContent` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.DataSpecificationContent` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return data_specification_content_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def data_specification_content_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.DataSpecificationContent:
    """
    Read an instance of :py:class:`.types.DataSpecificationContent` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.data_specification_content_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.DataSpecificationContent` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.DataSpecificationContent` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return data_specification_content_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def data_specification_content_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.DataSpecificationContent:
    """
    Read an instance of :py:class:`.types.DataSpecificationContent` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.data_specification_content_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.DataSpecificationContent` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.DataSpecificationContent` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return data_specification_content_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def embedded_data_specification_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.EmbeddedDataSpecification:
    """
    Read an instance of :py:class:`.types.EmbeddedDataSpecification` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.embedded_data_specification_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.EmbeddedDataSpecification` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for EmbeddedDataSpecification, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for EmbeddedDataSpecification, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_embedded_data_specification_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def embedded_data_specification_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.EmbeddedDataSpecification:
    """
    Read an instance of :py:class:`.types.EmbeddedDataSpecification` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.embedded_data_specification_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.EmbeddedDataSpecification` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.EmbeddedDataSpecification` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return embedded_data_specification_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def embedded_data_specification_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.EmbeddedDataSpecification:
    """
    Read an instance of :py:class:`.types.EmbeddedDataSpecification` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.embedded_data_specification_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.EmbeddedDataSpecification` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.EmbeddedDataSpecification` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return embedded_data_specification_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def embedded_data_specification_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.EmbeddedDataSpecification:
    """
    Read an instance of :py:class:`.types.EmbeddedDataSpecification` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.embedded_data_specification_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.EmbeddedDataSpecification` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.EmbeddedDataSpecification` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return embedded_data_specification_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def level_type_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.LevelType:
    """
    Read an instance of :py:class:`.types.LevelType` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.level_type_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LevelType` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for LevelType, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for LevelType, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_level_type_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def level_type_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.LevelType:
    """
    Read an instance of :py:class:`.types.LevelType` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.level_type_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.LevelType` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LevelType` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return level_type_from_iterparse(_with_elements_cleared_after_yield(iterator))


def level_type_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.LevelType:
    """
    Read an instance of :py:class:`.types.LevelType` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.level_type_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.LevelType` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LevelType` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return level_type_from_iterparse(_with_elements_cleared_after_yield(iterator))


def level_type_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.LevelType:
    """
    Read an instance of :py:class:`.types.LevelType` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.level_type_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.LevelType` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LevelType` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return level_type_from_iterparse(_with_elements_cleared_after_yield(iterator))


def value_reference_pair_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.ValueReferencePair:
    """
    Read an instance of :py:class:`.types.ValueReferencePair` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.value_reference_pair_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.ValueReferencePair` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for ValueReferencePair, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for ValueReferencePair, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_value_reference_pair_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def value_reference_pair_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.ValueReferencePair:
    """
    Read an instance of :py:class:`.types.ValueReferencePair` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.value_reference_pair_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.ValueReferencePair` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.ValueReferencePair` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return value_reference_pair_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def value_reference_pair_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.ValueReferencePair:
    """
    Read an instance of :py:class:`.types.ValueReferencePair` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.value_reference_pair_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.ValueReferencePair` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.ValueReferencePair` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return value_reference_pair_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def value_reference_pair_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.ValueReferencePair:
    """
    Read an instance of :py:class:`.types.ValueReferencePair` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.value_reference_pair_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.ValueReferencePair` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.ValueReferencePair` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return value_reference_pair_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def value_list_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.ValueList:
    """
    Read an instance of :py:class:`.types.ValueList` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.value_list_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.ValueList` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for ValueList, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for ValueList, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_value_list_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def value_list_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.ValueList:
    """
    Read an instance of :py:class:`.types.ValueList` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.value_list_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.ValueList` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.ValueList` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return value_list_from_iterparse(_with_elements_cleared_after_yield(iterator))


def value_list_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.ValueList:
    """
    Read an instance of :py:class:`.types.ValueList` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.value_list_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.ValueList` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.ValueList` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return value_list_from_iterparse(_with_elements_cleared_after_yield(iterator))


def value_list_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.ValueList:
    """
    Read an instance of :py:class:`.types.ValueList` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.value_list_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.ValueList` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.ValueList` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return value_list_from_iterparse(_with_elements_cleared_after_yield(iterator))


def lang_string_preferred_name_type_iec_61360_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.LangStringPreferredNameTypeIEC61360:
    """
    Read an instance of :py:class:`.types.LangStringPreferredNameTypeIEC61360` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.lang_string_preferred_name_type_iec_61360_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringPreferredNameTypeIEC61360` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for LangStringPreferredNameTypeIEC61360, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for LangStringPreferredNameTypeIEC61360, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_lang_string_preferred_name_type_iec_61360_as_element(
            next_element, iterator
        )
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def lang_string_preferred_name_type_iec_61360_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.LangStringPreferredNameTypeIEC61360:
    """
    Read an instance of :py:class:`.types.LangStringPreferredNameTypeIEC61360` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.lang_string_preferred_name_type_iec_61360_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.LangStringPreferredNameTypeIEC61360` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringPreferredNameTypeIEC61360` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return lang_string_preferred_name_type_iec_61360_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def lang_string_preferred_name_type_iec_61360_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.LangStringPreferredNameTypeIEC61360:
    """
    Read an instance of :py:class:`.types.LangStringPreferredNameTypeIEC61360` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.lang_string_preferred_name_type_iec_61360_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.LangStringPreferredNameTypeIEC61360` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringPreferredNameTypeIEC61360` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return lang_string_preferred_name_type_iec_61360_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def lang_string_preferred_name_type_iec_61360_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.LangStringPreferredNameTypeIEC61360:
    """
    Read an instance of :py:class:`.types.LangStringPreferredNameTypeIEC61360` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.lang_string_preferred_name_type_iec_61360_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.LangStringPreferredNameTypeIEC61360` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringPreferredNameTypeIEC61360` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return lang_string_preferred_name_type_iec_61360_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def lang_string_short_name_type_iec_61360_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.LangStringShortNameTypeIEC61360:
    """
    Read an instance of :py:class:`.types.LangStringShortNameTypeIEC61360` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.lang_string_short_name_type_iec_61360_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringShortNameTypeIEC61360` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for LangStringShortNameTypeIEC61360, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for LangStringShortNameTypeIEC61360, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_lang_string_short_name_type_iec_61360_as_element(
            next_element, iterator
        )
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def lang_string_short_name_type_iec_61360_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.LangStringShortNameTypeIEC61360:
    """
    Read an instance of :py:class:`.types.LangStringShortNameTypeIEC61360` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.lang_string_short_name_type_iec_61360_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.LangStringShortNameTypeIEC61360` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringShortNameTypeIEC61360` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return lang_string_short_name_type_iec_61360_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def lang_string_short_name_type_iec_61360_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.LangStringShortNameTypeIEC61360:
    """
    Read an instance of :py:class:`.types.LangStringShortNameTypeIEC61360` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.lang_string_short_name_type_iec_61360_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.LangStringShortNameTypeIEC61360` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringShortNameTypeIEC61360` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return lang_string_short_name_type_iec_61360_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def lang_string_short_name_type_iec_61360_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.LangStringShortNameTypeIEC61360:
    """
    Read an instance of :py:class:`.types.LangStringShortNameTypeIEC61360` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.lang_string_short_name_type_iec_61360_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.LangStringShortNameTypeIEC61360` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringShortNameTypeIEC61360` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return lang_string_short_name_type_iec_61360_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def lang_string_definition_type_iec_61360_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.LangStringDefinitionTypeIEC61360:
    """
    Read an instance of :py:class:`.types.LangStringDefinitionTypeIEC61360` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.lang_string_definition_type_iec_61360_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringDefinitionTypeIEC61360` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for LangStringDefinitionTypeIEC61360, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for LangStringDefinitionTypeIEC61360, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_lang_string_definition_type_iec_61360_as_element(
            next_element, iterator
        )
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def lang_string_definition_type_iec_61360_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.LangStringDefinitionTypeIEC61360:
    """
    Read an instance of :py:class:`.types.LangStringDefinitionTypeIEC61360` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.lang_string_definition_type_iec_61360_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.LangStringDefinitionTypeIEC61360` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringDefinitionTypeIEC61360` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return lang_string_definition_type_iec_61360_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def lang_string_definition_type_iec_61360_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.LangStringDefinitionTypeIEC61360:
    """
    Read an instance of :py:class:`.types.LangStringDefinitionTypeIEC61360` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.lang_string_definition_type_iec_61360_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.LangStringDefinitionTypeIEC61360` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringDefinitionTypeIEC61360` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return lang_string_definition_type_iec_61360_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def lang_string_definition_type_iec_61360_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.LangStringDefinitionTypeIEC61360:
    """
    Read an instance of :py:class:`.types.LangStringDefinitionTypeIEC61360` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.lang_string_definition_type_iec_61360_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.LangStringDefinitionTypeIEC61360` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.LangStringDefinitionTypeIEC61360` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return lang_string_definition_type_iec_61360_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def data_specification_iec_61360_from_iterparse(
    iterator: Iterator[Tuple[str, Element]],
) -> aas_types.DataSpecificationIEC61360:
    """
    Read an instance of :py:class:`.types.DataSpecificationIEC61360` from
    the :paramref:`iterator`.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.data_specification_iec_61360_from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.DataSpecificationIEC61360` read from
        :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element for DataSpecificationIEC61360, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element for DataSpecificationIEC61360, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_data_specification_iec_61360_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def data_specification_iec_61360_from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.DataSpecificationIEC61360:
    """
    Read an instance of :py:class:`.types.DataSpecificationIEC61360` from
    the :paramref:`stream`.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.data_specification_iec_61360_from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance of
        :py:class:`.types.DataSpecificationIEC61360` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.DataSpecificationIEC61360` read from
        :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return data_specification_iec_61360_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def data_specification_iec_61360_from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.DataSpecificationIEC61360:
    """
    Read an instance of :py:class:`.types.DataSpecificationIEC61360` from
    the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.data_specification_iec_61360_from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance of
        :py:class:`.types.DataSpecificationIEC61360` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.DataSpecificationIEC61360` read from
        :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return data_specification_iec_61360_from_iterparse(
            _with_elements_cleared_after_yield(iterator)
        )


def data_specification_iec_61360_from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.DataSpecificationIEC61360:
    """
    Read an instance of :py:class:`.types.DataSpecificationIEC61360` from
    the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.data_specification_iec_61360_from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance of
        :py:class:`.types.DataSpecificationIEC61360` in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.DataSpecificationIEC61360` read from
        :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return data_specification_iec_61360_from_iterparse(
        _with_elements_cleared_after_yield(iterator)
    )


def from_iterparse(iterator: Iterator[Tuple[str, Element]]) -> aas_types.Class:
    """
    Read an instance from the :paramref:`iterator`.

    The type of the instance is determined by the very first start element.

    Example usage:

    .. code-block::

        import pathlib
        import xml.etree.ElementTree as ET

        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        with path.open("rt") as fid:
            iterator = ET.iterparse(
                source=fid,
                events=['start', 'end']
            )
            instance = aas_xmlization.from_iterparse(
                iterator
            )

        # Do something with the ``instance``

    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance of :py:class:`.types.Class` read from the :paramref:`iterator`
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            # fmt: off
            "Expected the start element of an instance, "
            "but got the end-of-input"
            # fmt: on
        )

    next_event, next_element = next_event_element
    if next_event != "start":
        raise DeserializationException(
            f"Expected the start element of an instance, "
            f"but got event {next_event!r} and element {next_element.tag!r}"
        )

    try:
        return _read_as_element(next_element, iterator)
    except DeserializationException as exception:
        exception.path._prepend(ElementSegment(next_element))
        raise exception


def from_stream(
    stream: TextIO, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Class:
    """
    Read an instance from the :paramref:`stream`.

    The type of the instance is determined by the very first start element.

    Example usage:

    .. code-block::

        import aas_core3.xmlization as aas_xmlization

        with open_some_stream_over_network(...) as stream:
            instance = aas_xmlization.from_stream(
                stream
            )

        # Do something with the ``instance``

    :param stream:
        representing an instance in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance read from :paramref:`stream`
    """
    iterator = has_iterparse.iterparse(stream, ["start", "end"])
    return from_iterparse(_with_elements_cleared_after_yield(iterator))


def from_file(
    path: PathLike, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Class:
    """
    Read an instance from the file at the :paramref:`path`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        path = pathlib.Path(...)
        instance = aas_xmlization.from_file(
            path
        )

        # Do something with the ``instance``

    :param path:
        to the file representing an instance in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance read from the file at :paramref:`path`
    """
    with open(os.fspath(path), "rt", encoding="utf-8") as fid:
        iterator = has_iterparse.iterparse(fid, ["start", "end"])
        return from_iterparse(_with_elements_cleared_after_yield(iterator))


def from_str(
    text: str, has_iterparse: HasIterparse = xml.etree.ElementTree
) -> aas_types.Class:
    """
    Read an instance from the :paramref:`text`.

    Example usage:

    .. code-block::

        import pathlib
        import aas_core3.xmlization as aas_xmlization

        text = "<...>...</...>"
        instance = aas_xmlization.from_str(
            text
        )

        # Do something with the ``instance``

    :param text:
        representing an instance in XML
    :param has_iterparse:
        Module containing ``iterparse`` function.

        Default is to use :py:mod:`xml.etree.ElementTree` from the standard
        library. If you have to deal with malicious input, consider using
        a library such as `defusedxml.ElementTree`_.
    :raise: :py:class:`DeserializationException` if unexpected input
    :return:
        Instance read from :paramref:`text`
    """
    iterator = has_iterparse.iterparse(io.StringIO(text), ["start", "end"])
    return from_iterparse(_with_elements_cleared_after_yield(iterator))


# NOTE (mristin, 2022-10-08):
# Directly using the iterator turned out to result in very complex function
# designs. The design became much simpler as soon as we considered one look-ahead
# element. We came up finally with the following pattern which all the protected
# reading functions below roughly follow:
#
# ..code-block::
#
#    _read_*(
#       look-ahead element,
#       iterator
#    ) -> result
#
# The reading functions all read from the ``iterator`` coming from
# :py:func:`xml.etree.ElementTree.iterparse` with the argument
# ``events=["start", "end"]``. The exception :py:class:`.DeserializationException`
# is raised in case of unexpected input.
#
# The reading functions are responsible to read the end element corresponding to the
# start look-ahead element.
#
# When it comes to error reporting, we use exceptions. The exceptions are raised in
# the *callee*, as usual. However, the context of the exception, such as the error path,
# is added in the *caller*, as only the caller knows the context of
# the lookahead-element. In particular, prepending the path segment corresponding to
# the lookahead-element is the responsibility of the *caller*, and not of
# the *callee*.


def _parse_element_tag(element: Element) -> str:
    """
    Extract the tag name without the namespace prefix from :paramref:`element`.

    :param element: whose tag without namespace we want to extract
    :return: tag name without the namespace prefix
    :raise: :py:class:`DeserializationException` if unexpected :paramref:`element`
    """
    if not element.tag.startswith(_NAMESPACE_IN_CURLY_BRACKETS):
        namespace, got_namespace, tag_wo_ns = element.tag.rpartition("}")
        if got_namespace:
            if namespace.startswith("{"):
                namespace = namespace[1:]

            raise DeserializationException(
                f"Expected the element in the namespace {NAMESPACE!r}, "
                f"but got the element {tag_wo_ns!r} in the namespace {namespace!r}"
            )
        else:
            raise DeserializationException(
                f"Expected the element in the namespace {NAMESPACE!r}, "
                f"but got the element {tag_wo_ns!r} without the namespace prefix"
            )

    return element.tag[len(_NAMESPACE_IN_CURLY_BRACKETS) :]


def _raise_if_has_tail_or_attrib(element: Element) -> None:
    """
    Check that :paramref:`element` has no trailing text and no attributes.

    :param element: to be verified
    :raise:
        :py:class:`.DeserializationException` if trailing text or attributes;
        conforming to the convention about handling error paths,
        the exception path is left empty.
    """
    if element.tail is not None and len(element.tail.strip()) != 0:
        raise DeserializationException(
            f"Expected no trailing text, but got: {element.tail!r}"
        )

    if element.attrib is not None and len(element.attrib) > 0:
        raise DeserializationException(
            f"Expected no attributes, but got: {element.attrib}"
        )


def _read_end_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> Element:
    """
    Read the end element corresponding to the start :paramref:`element`
    from :paramref:`iterator`.

    :param element: corresponding start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    """
    next_event_element = next(iterator, None)
    if next_event_element is None:
        raise DeserializationException(
            f"Expected the end element for {element.tag}, " f"but got the end-of-input"
        )

    next_event, next_element = next_event_element
    if next_event != "end" or next_element.tag != element.tag:
        raise DeserializationException(
            f"Expected the end element for {element.tag!r}, "
            f"but got the event {next_event!r} and element {next_element.tag!r}"
        )

    _raise_if_has_tail_or_attrib(next_element)

    return next_element


def _read_text_from_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> str:
    """
    Extract the text from the :paramref:`element`, and read
    the end element from :paramref:`iterator`.

    The :paramref:`element` is expected to contain text. Otherwise,
    it is considered as unexpected input.

    :param element: start element enclosing the text
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    """
    _raise_if_has_tail_or_attrib(element)

    text = element.text

    end_element = _read_end_element(
        element,
        iterator,
    )

    if text is None:
        if end_element.text is None:
            raise DeserializationException(
                "Expected an element with text, but got an element with no text."
            )

        text = end_element.text

    return text


_XS_BOOLEAN_LITERAL_SET = {
    "1",
    "true",
    "0",
    "false",
}


def _read_bool_from_element_text(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> bool:
    """
    Parse the text of :paramref:`element` as a boolean, and
    read the corresponding end element from :paramref:`iterator`.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed value
    """
    text = _read_text_from_element(element, iterator)

    if text not in _XS_BOOLEAN_LITERAL_SET:
        raise DeserializationException(
            f"Expected a boolean, " f"but got an element with text: {text!r}"
        )

    return text in ("1", "true")


def _read_int_from_element_text(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> int:
    """
    Parse the text of :paramref:`element` as an integer, and
    read the corresponding end element from :paramref:`iterator`.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed value
    """
    text = _read_text_from_element(element, iterator)

    try:
        value = int(text)
    except ValueError:
        # pylint: disable=raise-missing-from
        raise DeserializationException(
            f"Expected an integer, " f"but got an element with text: {text!r}"
        )

    return value


_TEXT_TO_XS_DOUBLE_LITERALS = {
    "NaN": math.nan,
    "INF": math.inf,
    "-INF": -math.inf,
}


def _read_float_from_element_text(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> float:
    """
    Parse the text of :paramref:`element` as a floating-point number, and
    read the corresponding end element from :paramref:`iterator`.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed value
    """
    text = _read_text_from_element(element, iterator)

    value = _TEXT_TO_XS_DOUBLE_LITERALS.get(text, None)
    if value is None:
        try:
            value = float(text)
        except ValueError:
            # pylint: disable=raise-missing-from
            raise DeserializationException(
                f"Expected a floating-point number, "
                f"but got an element with text: {text!r}"
            )

    return value


def _read_str_from_element_text(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> str:
    """
    Parse the text of :paramref:`element` as a string, and
    read the corresponding end element from :paramref:`iterator`.

    If there is no text, empty string is returned.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed value
    """
    # NOTE (mristin, 2022-10-26):
    # We do not use ``_read_text_from_element`` as that function expects
    # the ``element`` to contain *some* text. In contrast, this function
    # can also deal with empty text, in which case it returns an empty string.

    text = element.text

    end_element = _read_end_element(element, iterator)

    if text is None:
        text = end_element.text

    _raise_if_has_tail_or_attrib(element)
    result = text if text is not None else ""

    return result


def _read_bytes_from_element_text(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> bytes:
    """
    Parse the text of :paramref:`element` as base64-encoded bytes, and
    read the corresponding end element from :paramref:`iterator`.

    :param element: look-ahead element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed value
    """
    text = _read_text_from_element(element, iterator)

    try:
        value = base64.b64decode(text)
    except Exception:
        # pylint: disable=raise-missing-from
        raise DeserializationException(
            f"Expected a text as base64-encoded bytes, "
            f"but got an element with text: {text!r}"
        )

    return value


def _read_has_semantics_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.HasSemantics:
    """
    Read an instance of :py:class:`.types.HasSemantics` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)
    read_as_sequence = _DISPATCH_FOR_HAS_SEMANTICS.get(tag_wo_ns, None)

    if read_as_sequence is None:
        raise DeserializationException(
            f"Expected the element tag to be a valid model type "
            f"of a concrete instance of 'HasSemantics', "
            f"but got tag {tag_wo_ns!r}"
        )

    return read_as_sequence(element, iterator)


class _ReaderAndSetterForExtension:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`Extension`.

    The properties correspond to the constructor arguments of
    :py:class:`Extension`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.semantic_id: Optional[aas_types.Reference] = None
        self.supplemental_semantic_ids: Optional[List[aas_types.Reference]] = None
        self.name: Optional[str] = None
        self.value_type: Optional[aas_types.DataTypeDefXSD] = None
        self.value: Optional[str] = None
        self.refers_to: Optional[List[aas_types.Reference]] = None

    def read_and_set_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Extension.semantic_id` and set it.
        """
        self.semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_supplemental_semantic_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Extension.supplemental_semantic_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.supplemental_semantic_ids = result

    def read_and_set_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Extension.name` and set it.
        """
        self.name = _read_str_from_element_text(element, iterator)

    def read_and_set_value_type(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Extension.value_type` and set it.
        """
        self.value_type = _read_data_type_def_xsd_from_element_text(element, iterator)

    def read_and_set_value(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Extension.value` and set it.
        """
        self.value = _read_str_from_element_text(element, iterator)

    def read_and_set_refers_to(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Extension.refers_to` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.refers_to = result


def _read_extension_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Extension:
    """
    Read an instance of :py:class:`.types.Extension`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForExtension()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_EXTENSION.get(tag_wo_ns, None)
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.name is None:
        raise DeserializationException("The required property 'name' is missing")

    return aas_types.Extension(
        reader_and_setter.name,
        reader_and_setter.semantic_id,
        reader_and_setter.supplemental_semantic_ids,
        reader_and_setter.value_type,
        reader_and_setter.value,
        reader_and_setter.refers_to,
    )


def _read_extension_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Extension:
    """
    Read an instance of :py:class:`.types.Extension` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "extension":
        raise DeserializationException(
            f"Expected the element with the tag 'extension', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_extension_as_sequence(element, iterator)


def _read_has_extensions_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.HasExtensions:
    """
    Read an instance of :py:class:`.types.HasExtensions` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)
    read_as_sequence = _DISPATCH_FOR_HAS_EXTENSIONS.get(tag_wo_ns, None)

    if read_as_sequence is None:
        raise DeserializationException(
            f"Expected the element tag to be a valid model type "
            f"of a concrete instance of 'HasExtensions', "
            f"but got tag {tag_wo_ns!r}"
        )

    return read_as_sequence(element, iterator)


def _read_referable_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Referable:
    """
    Read an instance of :py:class:`.types.Referable` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)
    read_as_sequence = _DISPATCH_FOR_REFERABLE.get(tag_wo_ns, None)

    if read_as_sequence is None:
        raise DeserializationException(
            f"Expected the element tag to be a valid model type "
            f"of a concrete instance of 'Referable', "
            f"but got tag {tag_wo_ns!r}"
        )

    return read_as_sequence(element, iterator)


def _read_identifiable_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Identifiable:
    """
    Read an instance of :py:class:`.types.Identifiable` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)
    read_as_sequence = _DISPATCH_FOR_IDENTIFIABLE.get(tag_wo_ns, None)

    if read_as_sequence is None:
        raise DeserializationException(
            f"Expected the element tag to be a valid model type "
            f"of a concrete instance of 'Identifiable', "
            f"but got tag {tag_wo_ns!r}"
        )

    return read_as_sequence(element, iterator)


def _read_modelling_kind_from_element_text(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.ModellingKind:
    """
    Parse the text of :paramref:`element` as a literal of
    :py:class:`.types.ModellingKind`, and read the corresponding
    end element from :paramref:`iterator`.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed value
    """
    text = _read_text_from_element(element, iterator)

    literal = aas_stringification.modelling_kind_from_str(text)
    if literal is None:
        raise DeserializationException(
            f"Not a valid string representation of "
            f"a literal of ModellingKind: {text}"
        )

    return literal


def _read_has_kind_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.HasKind:
    """
    Read an instance of :py:class:`.types.HasKind` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)
    read_as_sequence = _DISPATCH_FOR_HAS_KIND.get(tag_wo_ns, None)

    if read_as_sequence is None:
        raise DeserializationException(
            f"Expected the element tag to be a valid model type "
            f"of a concrete instance of 'HasKind', "
            f"but got tag {tag_wo_ns!r}"
        )

    return read_as_sequence(element, iterator)


def _read_has_data_specification_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.HasDataSpecification:
    """
    Read an instance of :py:class:`.types.HasDataSpecification` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)
    read_as_sequence = _DISPATCH_FOR_HAS_DATA_SPECIFICATION.get(tag_wo_ns, None)

    if read_as_sequence is None:
        raise DeserializationException(
            f"Expected the element tag to be a valid model type "
            f"of a concrete instance of 'HasDataSpecification', "
            f"but got tag {tag_wo_ns!r}"
        )

    return read_as_sequence(element, iterator)


class _ReaderAndSetterForAdministrativeInformation:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`AdministrativeInformation`.

    The properties correspond to the constructor arguments of
    :py:class:`AdministrativeInformation`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.embedded_data_specifications: Optional[
            List[aas_types.EmbeddedDataSpecification]
        ] = None
        self.version: Optional[str] = None
        self.revision: Optional[str] = None
        self.creator: Optional[aas_types.Reference] = None
        self.template_id: Optional[str] = None

    def read_and_set_embedded_data_specifications(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AdministrativeInformation.embedded_data_specifications` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.EmbeddedDataSpecification] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_embedded_data_specification_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.embedded_data_specifications = result

    def read_and_set_version(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AdministrativeInformation.version` and set it.
        """
        self.version = _read_str_from_element_text(element, iterator)

    def read_and_set_revision(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AdministrativeInformation.revision` and set it.
        """
        self.revision = _read_str_from_element_text(element, iterator)

    def read_and_set_creator(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AdministrativeInformation.creator` and set it.
        """
        self.creator = _read_reference_as_sequence(element, iterator)

    def read_and_set_template_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AdministrativeInformation.template_id` and set it.
        """
        self.template_id = _read_str_from_element_text(element, iterator)


def _read_administrative_information_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.AdministrativeInformation:
    """
    Read an instance of :py:class:`.types.AdministrativeInformation`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForAdministrativeInformation()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_ADMINISTRATIVE_INFORMATION.get(
            tag_wo_ns, None
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    return aas_types.AdministrativeInformation(
        reader_and_setter.embedded_data_specifications,
        reader_and_setter.version,
        reader_and_setter.revision,
        reader_and_setter.creator,
        reader_and_setter.template_id,
    )


def _read_administrative_information_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.AdministrativeInformation:
    """
    Read an instance of :py:class:`.types.AdministrativeInformation` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "administrativeInformation":
        raise DeserializationException(
            f"Expected the element with the tag 'administrativeInformation', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_administrative_information_as_sequence(element, iterator)


def _read_qualifiable_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Qualifiable:
    """
    Read an instance of :py:class:`.types.Qualifiable` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)
    read_as_sequence = _DISPATCH_FOR_QUALIFIABLE.get(tag_wo_ns, None)

    if read_as_sequence is None:
        raise DeserializationException(
            f"Expected the element tag to be a valid model type "
            f"of a concrete instance of 'Qualifiable', "
            f"but got tag {tag_wo_ns!r}"
        )

    return read_as_sequence(element, iterator)


def _read_qualifier_kind_from_element_text(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.QualifierKind:
    """
    Parse the text of :paramref:`element` as a literal of
    :py:class:`.types.QualifierKind`, and read the corresponding
    end element from :paramref:`iterator`.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed value
    """
    text = _read_text_from_element(element, iterator)

    literal = aas_stringification.qualifier_kind_from_str(text)
    if literal is None:
        raise DeserializationException(
            f"Not a valid string representation of "
            f"a literal of QualifierKind: {text}"
        )

    return literal


class _ReaderAndSetterForQualifier:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`Qualifier`.

    The properties correspond to the constructor arguments of
    :py:class:`Qualifier`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.semantic_id: Optional[aas_types.Reference] = None
        self.supplemental_semantic_ids: Optional[List[aas_types.Reference]] = None
        self.kind: Optional[aas_types.QualifierKind] = None
        self.type: Optional[str] = None
        self.value_type: Optional[aas_types.DataTypeDefXSD] = None
        self.value: Optional[str] = None
        self.value_id: Optional[aas_types.Reference] = None

    def read_and_set_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Qualifier.semantic_id` and set it.
        """
        self.semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_supplemental_semantic_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Qualifier.supplemental_semantic_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.supplemental_semantic_ids = result

    def read_and_set_kind(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Qualifier.kind` and set it.
        """
        self.kind = _read_qualifier_kind_from_element_text(element, iterator)

    def read_and_set_type(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Qualifier.type` and set it.
        """
        self.type = _read_str_from_element_text(element, iterator)

    def read_and_set_value_type(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Qualifier.value_type` and set it.
        """
        self.value_type = _read_data_type_def_xsd_from_element_text(element, iterator)

    def read_and_set_value(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Qualifier.value` and set it.
        """
        self.value = _read_str_from_element_text(element, iterator)

    def read_and_set_value_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Qualifier.value_id` and set it.
        """
        self.value_id = _read_reference_as_sequence(element, iterator)


def _read_qualifier_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Qualifier:
    """
    Read an instance of :py:class:`.types.Qualifier`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForQualifier()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_QUALIFIER.get(tag_wo_ns, None)
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.type is None:
        raise DeserializationException("The required property 'type' is missing")

    if reader_and_setter.value_type is None:
        raise DeserializationException("The required property 'valueType' is missing")

    return aas_types.Qualifier(
        reader_and_setter.type,
        reader_and_setter.value_type,
        reader_and_setter.semantic_id,
        reader_and_setter.supplemental_semantic_ids,
        reader_and_setter.kind,
        reader_and_setter.value,
        reader_and_setter.value_id,
    )


def _read_qualifier_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Qualifier:
    """
    Read an instance of :py:class:`.types.Qualifier` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "qualifier":
        raise DeserializationException(
            f"Expected the element with the tag 'qualifier', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_qualifier_as_sequence(element, iterator)


class _ReaderAndSetterForAssetAdministrationShell:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`AssetAdministrationShell`.

    The properties correspond to the constructor arguments of
    :py:class:`AssetAdministrationShell`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.extensions: Optional[List[aas_types.Extension]] = None
        self.category: Optional[str] = None
        self.id_short: Optional[str] = None
        self.display_name: Optional[List[aas_types.LangStringNameType]] = None
        self.description: Optional[List[aas_types.LangStringTextType]] = None
        self.administration: Optional[aas_types.AdministrativeInformation] = None
        self.id: Optional[str] = None
        self.embedded_data_specifications: Optional[
            List[aas_types.EmbeddedDataSpecification]
        ] = None
        self.derived_from: Optional[aas_types.Reference] = None
        self.asset_information: Optional[aas_types.AssetInformation] = None
        self.submodels: Optional[List[aas_types.Reference]] = None

    def read_and_set_extensions(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AssetAdministrationShell.extensions` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Extension] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_extension_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.extensions = result

    def read_and_set_category(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AssetAdministrationShell.category` and set it.
        """
        self.category = _read_str_from_element_text(element, iterator)

    def read_and_set_id_short(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AssetAdministrationShell.id_short` and set it.
        """
        self.id_short = _read_str_from_element_text(element, iterator)

    def read_and_set_display_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AssetAdministrationShell.display_name` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringNameType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_name_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.display_name = result

    def read_and_set_description(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AssetAdministrationShell.description` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringTextType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_text_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.description = result

    def read_and_set_administration(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AssetAdministrationShell.administration` and set it.
        """
        self.administration = _read_administrative_information_as_sequence(
            element, iterator
        )

    def read_and_set_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AssetAdministrationShell.id` and set it.
        """
        self.id = _read_str_from_element_text(element, iterator)

    def read_and_set_embedded_data_specifications(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AssetAdministrationShell.embedded_data_specifications` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.EmbeddedDataSpecification] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_embedded_data_specification_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.embedded_data_specifications = result

    def read_and_set_derived_from(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AssetAdministrationShell.derived_from` and set it.
        """
        self.derived_from = _read_reference_as_sequence(element, iterator)

    def read_and_set_asset_information(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AssetAdministrationShell.asset_information` and set it.
        """
        self.asset_information = _read_asset_information_as_sequence(element, iterator)

    def read_and_set_submodels(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AssetAdministrationShell.submodels` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.submodels = result


def _read_asset_administration_shell_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.AssetAdministrationShell:
    """
    Read an instance of :py:class:`.types.AssetAdministrationShell`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForAssetAdministrationShell()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_ASSET_ADMINISTRATION_SHELL.get(
            tag_wo_ns, None
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.id is None:
        raise DeserializationException("The required property 'id' is missing")

    if reader_and_setter.asset_information is None:
        raise DeserializationException(
            "The required property 'assetInformation' is missing"
        )

    return aas_types.AssetAdministrationShell(
        reader_and_setter.id,
        reader_and_setter.asset_information,
        reader_and_setter.extensions,
        reader_and_setter.category,
        reader_and_setter.id_short,
        reader_and_setter.display_name,
        reader_and_setter.description,
        reader_and_setter.administration,
        reader_and_setter.embedded_data_specifications,
        reader_and_setter.derived_from,
        reader_and_setter.submodels,
    )


def _read_asset_administration_shell_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.AssetAdministrationShell:
    """
    Read an instance of :py:class:`.types.AssetAdministrationShell` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "assetAdministrationShell":
        raise DeserializationException(
            f"Expected the element with the tag 'assetAdministrationShell', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_asset_administration_shell_as_sequence(element, iterator)


class _ReaderAndSetterForAssetInformation:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`AssetInformation`.

    The properties correspond to the constructor arguments of
    :py:class:`AssetInformation`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.asset_kind: Optional[aas_types.AssetKind] = None
        self.global_asset_id: Optional[str] = None
        self.specific_asset_ids: Optional[List[aas_types.SpecificAssetID]] = None
        self.asset_type: Optional[str] = None
        self.default_thumbnail: Optional[aas_types.Resource] = None

    def read_and_set_asset_kind(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AssetInformation.asset_kind` and set it.
        """
        self.asset_kind = _read_asset_kind_from_element_text(element, iterator)

    def read_and_set_global_asset_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AssetInformation.global_asset_id` and set it.
        """
        self.global_asset_id = _read_str_from_element_text(element, iterator)

    def read_and_set_specific_asset_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AssetInformation.specific_asset_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.SpecificAssetID] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_specific_asset_id_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.specific_asset_ids = result

    def read_and_set_asset_type(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AssetInformation.asset_type` and set it.
        """
        self.asset_type = _read_str_from_element_text(element, iterator)

    def read_and_set_default_thumbnail(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AssetInformation.default_thumbnail` and set it.
        """
        self.default_thumbnail = _read_resource_as_sequence(element, iterator)


def _read_asset_information_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.AssetInformation:
    """
    Read an instance of :py:class:`.types.AssetInformation`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForAssetInformation()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_ASSET_INFORMATION.get(
            tag_wo_ns, None
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.asset_kind is None:
        raise DeserializationException("The required property 'assetKind' is missing")

    return aas_types.AssetInformation(
        reader_and_setter.asset_kind,
        reader_and_setter.global_asset_id,
        reader_and_setter.specific_asset_ids,
        reader_and_setter.asset_type,
        reader_and_setter.default_thumbnail,
    )


def _read_asset_information_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.AssetInformation:
    """
    Read an instance of :py:class:`.types.AssetInformation` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "assetInformation":
        raise DeserializationException(
            f"Expected the element with the tag 'assetInformation', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_asset_information_as_sequence(element, iterator)


class _ReaderAndSetterForResource:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`Resource`.

    The properties correspond to the constructor arguments of
    :py:class:`Resource`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.path: Optional[str] = None
        self.content_type: Optional[str] = None

    def read_and_set_path(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Resource.path` and set it.
        """
        self.path = _read_str_from_element_text(element, iterator)

    def read_and_set_content_type(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Resource.content_type` and set it.
        """
        self.content_type = _read_str_from_element_text(element, iterator)


def _read_resource_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Resource:
    """
    Read an instance of :py:class:`.types.Resource`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForResource()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_RESOURCE.get(tag_wo_ns, None)
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.path is None:
        raise DeserializationException("The required property 'path' is missing")

    return aas_types.Resource(reader_and_setter.path, reader_and_setter.content_type)


def _read_resource_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Resource:
    """
    Read an instance of :py:class:`.types.Resource` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "resource":
        raise DeserializationException(
            f"Expected the element with the tag 'resource', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_resource_as_sequence(element, iterator)


def _read_asset_kind_from_element_text(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.AssetKind:
    """
    Parse the text of :paramref:`element` as a literal of
    :py:class:`.types.AssetKind`, and read the corresponding
    end element from :paramref:`iterator`.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed value
    """
    text = _read_text_from_element(element, iterator)

    literal = aas_stringification.asset_kind_from_str(text)
    if literal is None:
        raise DeserializationException(
            f"Not a valid string representation of " f"a literal of AssetKind: {text}"
        )

    return literal


class _ReaderAndSetterForSpecificAssetID:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`SpecificAssetID`.

    The properties correspond to the constructor arguments of
    :py:class:`SpecificAssetID`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.semantic_id: Optional[aas_types.Reference] = None
        self.supplemental_semantic_ids: Optional[List[aas_types.Reference]] = None
        self.name: Optional[str] = None
        self.value: Optional[str] = None
        self.external_subject_id: Optional[aas_types.Reference] = None

    def read_and_set_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SpecificAssetID.semantic_id` and set it.
        """
        self.semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_supplemental_semantic_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SpecificAssetID.supplemental_semantic_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.supplemental_semantic_ids = result

    def read_and_set_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SpecificAssetID.name` and set it.
        """
        self.name = _read_str_from_element_text(element, iterator)

    def read_and_set_value(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SpecificAssetID.value` and set it.
        """
        self.value = _read_str_from_element_text(element, iterator)

    def read_and_set_external_subject_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SpecificAssetID.external_subject_id` and set it.
        """
        self.external_subject_id = _read_reference_as_sequence(element, iterator)


def _read_specific_asset_id_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.SpecificAssetID:
    """
    Read an instance of :py:class:`.types.SpecificAssetID`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForSpecificAssetID()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_SPECIFIC_ASSET_ID.get(
            tag_wo_ns, None
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.name is None:
        raise DeserializationException("The required property 'name' is missing")

    if reader_and_setter.value is None:
        raise DeserializationException("The required property 'value' is missing")

    return aas_types.SpecificAssetID(
        reader_and_setter.name,
        reader_and_setter.value,
        reader_and_setter.semantic_id,
        reader_and_setter.supplemental_semantic_ids,
        reader_and_setter.external_subject_id,
    )


def _read_specific_asset_id_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.SpecificAssetID:
    """
    Read an instance of :py:class:`.types.SpecificAssetID` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "specificAssetId":
        raise DeserializationException(
            f"Expected the element with the tag 'specificAssetId', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_specific_asset_id_as_sequence(element, iterator)


class _ReaderAndSetterForSubmodel:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`Submodel`.

    The properties correspond to the constructor arguments of
    :py:class:`Submodel`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.extensions: Optional[List[aas_types.Extension]] = None
        self.category: Optional[str] = None
        self.id_short: Optional[str] = None
        self.display_name: Optional[List[aas_types.LangStringNameType]] = None
        self.description: Optional[List[aas_types.LangStringTextType]] = None
        self.administration: Optional[aas_types.AdministrativeInformation] = None
        self.id: Optional[str] = None
        self.kind: Optional[aas_types.ModellingKind] = None
        self.semantic_id: Optional[aas_types.Reference] = None
        self.supplemental_semantic_ids: Optional[List[aas_types.Reference]] = None
        self.qualifiers: Optional[List[aas_types.Qualifier]] = None
        self.embedded_data_specifications: Optional[
            List[aas_types.EmbeddedDataSpecification]
        ] = None
        self.submodel_elements: Optional[List[aas_types.SubmodelElement]] = None

    def read_and_set_extensions(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Submodel.extensions` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Extension] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_extension_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.extensions = result

    def read_and_set_category(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Submodel.category` and set it.
        """
        self.category = _read_str_from_element_text(element, iterator)

    def read_and_set_id_short(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Submodel.id_short` and set it.
        """
        self.id_short = _read_str_from_element_text(element, iterator)

    def read_and_set_display_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Submodel.display_name` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringNameType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_name_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.display_name = result

    def read_and_set_description(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Submodel.description` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringTextType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_text_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.description = result

    def read_and_set_administration(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Submodel.administration` and set it.
        """
        self.administration = _read_administrative_information_as_sequence(
            element, iterator
        )

    def read_and_set_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Submodel.id` and set it.
        """
        self.id = _read_str_from_element_text(element, iterator)

    def read_and_set_kind(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Submodel.kind` and set it.
        """
        self.kind = _read_modelling_kind_from_element_text(element, iterator)

    def read_and_set_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Submodel.semantic_id` and set it.
        """
        self.semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_supplemental_semantic_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Submodel.supplemental_semantic_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.supplemental_semantic_ids = result

    def read_and_set_qualifiers(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Submodel.qualifiers` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Qualifier] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_qualifier_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.qualifiers = result

    def read_and_set_embedded_data_specifications(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Submodel.embedded_data_specifications` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.EmbeddedDataSpecification] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_embedded_data_specification_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.embedded_data_specifications = result

    def read_and_set_submodel_elements(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Submodel.submodel_elements` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.SubmodelElement] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_submodel_element_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.submodel_elements = result


def _read_submodel_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Submodel:
    """
    Read an instance of :py:class:`.types.Submodel`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForSubmodel()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_SUBMODEL.get(tag_wo_ns, None)
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.id is None:
        raise DeserializationException("The required property 'id' is missing")

    return aas_types.Submodel(
        reader_and_setter.id,
        reader_and_setter.extensions,
        reader_and_setter.category,
        reader_and_setter.id_short,
        reader_and_setter.display_name,
        reader_and_setter.description,
        reader_and_setter.administration,
        reader_and_setter.kind,
        reader_and_setter.semantic_id,
        reader_and_setter.supplemental_semantic_ids,
        reader_and_setter.qualifiers,
        reader_and_setter.embedded_data_specifications,
        reader_and_setter.submodel_elements,
    )


def _read_submodel_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Submodel:
    """
    Read an instance of :py:class:`.types.Submodel` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "submodel":
        raise DeserializationException(
            f"Expected the element with the tag 'submodel', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_submodel_as_sequence(element, iterator)


def _read_submodel_element_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.SubmodelElement:
    """
    Read an instance of :py:class:`.types.SubmodelElement` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)
    read_as_sequence = _DISPATCH_FOR_SUBMODEL_ELEMENT.get(tag_wo_ns, None)

    if read_as_sequence is None:
        raise DeserializationException(
            f"Expected the element tag to be a valid model type "
            f"of a concrete instance of 'SubmodelElement', "
            f"but got tag {tag_wo_ns!r}"
        )

    return read_as_sequence(element, iterator)


class _ReaderAndSetterForRelationshipElement:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`RelationshipElement`.

    The properties correspond to the constructor arguments of
    :py:class:`RelationshipElement`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.extensions: Optional[List[aas_types.Extension]] = None
        self.category: Optional[str] = None
        self.id_short: Optional[str] = None
        self.display_name: Optional[List[aas_types.LangStringNameType]] = None
        self.description: Optional[List[aas_types.LangStringTextType]] = None
        self.semantic_id: Optional[aas_types.Reference] = None
        self.supplemental_semantic_ids: Optional[List[aas_types.Reference]] = None
        self.qualifiers: Optional[List[aas_types.Qualifier]] = None
        self.embedded_data_specifications: Optional[
            List[aas_types.EmbeddedDataSpecification]
        ] = None
        self.first: Optional[aas_types.Reference] = None
        self.second: Optional[aas_types.Reference] = None

    def read_and_set_extensions(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.RelationshipElement.extensions` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Extension] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_extension_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.extensions = result

    def read_and_set_category(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.RelationshipElement.category` and set it.
        """
        self.category = _read_str_from_element_text(element, iterator)

    def read_and_set_id_short(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.RelationshipElement.id_short` and set it.
        """
        self.id_short = _read_str_from_element_text(element, iterator)

    def read_and_set_display_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.RelationshipElement.display_name` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringNameType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_name_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.display_name = result

    def read_and_set_description(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.RelationshipElement.description` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringTextType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_text_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.description = result

    def read_and_set_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.RelationshipElement.semantic_id` and set it.
        """
        self.semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_supplemental_semantic_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.RelationshipElement.supplemental_semantic_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.supplemental_semantic_ids = result

    def read_and_set_qualifiers(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.RelationshipElement.qualifiers` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Qualifier] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_qualifier_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.qualifiers = result

    def read_and_set_embedded_data_specifications(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.RelationshipElement.embedded_data_specifications` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.EmbeddedDataSpecification] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_embedded_data_specification_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.embedded_data_specifications = result

    def read_and_set_first(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.RelationshipElement.first` and set it.
        """
        self.first = _read_reference_as_sequence(element, iterator)

    def read_and_set_second(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.RelationshipElement.second` and set it.
        """
        self.second = _read_reference_as_sequence(element, iterator)


def _read_relationship_element_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.RelationshipElement:
    """
    Read an instance of :py:class:`.types.RelationshipElement`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForRelationshipElement()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_RELATIONSHIP_ELEMENT.get(
            tag_wo_ns, None
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.first is None:
        raise DeserializationException("The required property 'first' is missing")

    if reader_and_setter.second is None:
        raise DeserializationException("The required property 'second' is missing")

    return aas_types.RelationshipElement(
        reader_and_setter.first,
        reader_and_setter.second,
        reader_and_setter.extensions,
        reader_and_setter.category,
        reader_and_setter.id_short,
        reader_and_setter.display_name,
        reader_and_setter.description,
        reader_and_setter.semantic_id,
        reader_and_setter.supplemental_semantic_ids,
        reader_and_setter.qualifiers,
        reader_and_setter.embedded_data_specifications,
    )


def _read_relationship_element_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.RelationshipElement:
    """
    Read an instance of :py:class:`.types.RelationshipElement` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)
    read_as_sequence = _DISPATCH_FOR_RELATIONSHIP_ELEMENT.get(tag_wo_ns, None)

    if read_as_sequence is None:
        raise DeserializationException(
            f"Expected the element tag to be a valid model type "
            f"of a concrete instance of 'RelationshipElement', "
            f"but got tag {tag_wo_ns!r}"
        )

    return read_as_sequence(element, iterator)


def _read_aas_submodel_elements_from_element_text(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.AASSubmodelElements:
    """
    Parse the text of :paramref:`element` as a literal of
    :py:class:`.types.AASSubmodelElements`, and read the corresponding
    end element from :paramref:`iterator`.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed value
    """
    text = _read_text_from_element(element, iterator)

    literal = aas_stringification.aas_submodel_elements_from_str(text)
    if literal is None:
        raise DeserializationException(
            f"Not a valid string representation of "
            f"a literal of AASSubmodelElements: {text}"
        )

    return literal


class _ReaderAndSetterForSubmodelElementList:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`SubmodelElementList`.

    The properties correspond to the constructor arguments of
    :py:class:`SubmodelElementList`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.extensions: Optional[List[aas_types.Extension]] = None
        self.category: Optional[str] = None
        self.id_short: Optional[str] = None
        self.display_name: Optional[List[aas_types.LangStringNameType]] = None
        self.description: Optional[List[aas_types.LangStringTextType]] = None
        self.semantic_id: Optional[aas_types.Reference] = None
        self.supplemental_semantic_ids: Optional[List[aas_types.Reference]] = None
        self.qualifiers: Optional[List[aas_types.Qualifier]] = None
        self.embedded_data_specifications: Optional[
            List[aas_types.EmbeddedDataSpecification]
        ] = None
        self.order_relevant: Optional[bool] = None
        self.semantic_id_list_element: Optional[aas_types.Reference] = None
        self.type_value_list_element: Optional[aas_types.AASSubmodelElements] = None
        self.value_type_list_element: Optional[aas_types.DataTypeDefXSD] = None
        self.value: Optional[List[aas_types.SubmodelElement]] = None

    def read_and_set_extensions(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementList.extensions` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Extension] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_extension_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.extensions = result

    def read_and_set_category(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementList.category` and set it.
        """
        self.category = _read_str_from_element_text(element, iterator)

    def read_and_set_id_short(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementList.id_short` and set it.
        """
        self.id_short = _read_str_from_element_text(element, iterator)

    def read_and_set_display_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementList.display_name` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringNameType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_name_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.display_name = result

    def read_and_set_description(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementList.description` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringTextType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_text_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.description = result

    def read_and_set_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementList.semantic_id` and set it.
        """
        self.semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_supplemental_semantic_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementList.supplemental_semantic_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.supplemental_semantic_ids = result

    def read_and_set_qualifiers(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementList.qualifiers` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Qualifier] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_qualifier_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.qualifiers = result

    def read_and_set_embedded_data_specifications(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementList.embedded_data_specifications` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.EmbeddedDataSpecification] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_embedded_data_specification_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.embedded_data_specifications = result

    def read_and_set_order_relevant(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementList.order_relevant` and set it.
        """
        self.order_relevant = _read_bool_from_element_text(element, iterator)

    def read_and_set_semantic_id_list_element(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementList.semantic_id_list_element` and set it.
        """
        self.semantic_id_list_element = _read_reference_as_sequence(element, iterator)

    def read_and_set_type_value_list_element(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementList.type_value_list_element` and set it.
        """
        self.type_value_list_element = _read_aas_submodel_elements_from_element_text(
            element, iterator
        )

    def read_and_set_value_type_list_element(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementList.value_type_list_element` and set it.
        """
        self.value_type_list_element = _read_data_type_def_xsd_from_element_text(
            element, iterator
        )

    def read_and_set_value(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementList.value` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.SubmodelElement] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_submodel_element_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.value = result


def _read_submodel_element_list_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.SubmodelElementList:
    """
    Read an instance of :py:class:`.types.SubmodelElementList`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForSubmodelElementList()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_SUBMODEL_ELEMENT_LIST.get(
            tag_wo_ns, None
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.type_value_list_element is None:
        raise DeserializationException(
            "The required property 'typeValueListElement' is missing"
        )

    return aas_types.SubmodelElementList(
        reader_and_setter.type_value_list_element,
        reader_and_setter.extensions,
        reader_and_setter.category,
        reader_and_setter.id_short,
        reader_and_setter.display_name,
        reader_and_setter.description,
        reader_and_setter.semantic_id,
        reader_and_setter.supplemental_semantic_ids,
        reader_and_setter.qualifiers,
        reader_and_setter.embedded_data_specifications,
        reader_and_setter.order_relevant,
        reader_and_setter.semantic_id_list_element,
        reader_and_setter.value_type_list_element,
        reader_and_setter.value,
    )


def _read_submodel_element_list_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.SubmodelElementList:
    """
    Read an instance of :py:class:`.types.SubmodelElementList` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "submodelElementList":
        raise DeserializationException(
            f"Expected the element with the tag 'submodelElementList', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_submodel_element_list_as_sequence(element, iterator)


class _ReaderAndSetterForSubmodelElementCollection:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`SubmodelElementCollection`.

    The properties correspond to the constructor arguments of
    :py:class:`SubmodelElementCollection`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.extensions: Optional[List[aas_types.Extension]] = None
        self.category: Optional[str] = None
        self.id_short: Optional[str] = None
        self.display_name: Optional[List[aas_types.LangStringNameType]] = None
        self.description: Optional[List[aas_types.LangStringTextType]] = None
        self.semantic_id: Optional[aas_types.Reference] = None
        self.supplemental_semantic_ids: Optional[List[aas_types.Reference]] = None
        self.qualifiers: Optional[List[aas_types.Qualifier]] = None
        self.embedded_data_specifications: Optional[
            List[aas_types.EmbeddedDataSpecification]
        ] = None
        self.value: Optional[List[aas_types.SubmodelElement]] = None

    def read_and_set_extensions(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementCollection.extensions` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Extension] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_extension_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.extensions = result

    def read_and_set_category(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementCollection.category` and set it.
        """
        self.category = _read_str_from_element_text(element, iterator)

    def read_and_set_id_short(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementCollection.id_short` and set it.
        """
        self.id_short = _read_str_from_element_text(element, iterator)

    def read_and_set_display_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementCollection.display_name` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringNameType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_name_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.display_name = result

    def read_and_set_description(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementCollection.description` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringTextType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_text_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.description = result

    def read_and_set_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementCollection.semantic_id` and set it.
        """
        self.semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_supplemental_semantic_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementCollection.supplemental_semantic_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.supplemental_semantic_ids = result

    def read_and_set_qualifiers(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementCollection.qualifiers` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Qualifier] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_qualifier_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.qualifiers = result

    def read_and_set_embedded_data_specifications(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementCollection.embedded_data_specifications` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.EmbeddedDataSpecification] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_embedded_data_specification_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.embedded_data_specifications = result

    def read_and_set_value(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.SubmodelElementCollection.value` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.SubmodelElement] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_submodel_element_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.value = result


def _read_submodel_element_collection_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.SubmodelElementCollection:
    """
    Read an instance of :py:class:`.types.SubmodelElementCollection`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForSubmodelElementCollection()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = (
            _READ_AND_SET_DISPATCH_FOR_SUBMODEL_ELEMENT_COLLECTION.get(tag_wo_ns, None)
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    return aas_types.SubmodelElementCollection(
        reader_and_setter.extensions,
        reader_and_setter.category,
        reader_and_setter.id_short,
        reader_and_setter.display_name,
        reader_and_setter.description,
        reader_and_setter.semantic_id,
        reader_and_setter.supplemental_semantic_ids,
        reader_and_setter.qualifiers,
        reader_and_setter.embedded_data_specifications,
        reader_and_setter.value,
    )


def _read_submodel_element_collection_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.SubmodelElementCollection:
    """
    Read an instance of :py:class:`.types.SubmodelElementCollection` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "submodelElementCollection":
        raise DeserializationException(
            f"Expected the element with the tag 'submodelElementCollection', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_submodel_element_collection_as_sequence(element, iterator)


def _read_data_element_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.DataElement:
    """
    Read an instance of :py:class:`.types.DataElement` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)
    read_as_sequence = _DISPATCH_FOR_DATA_ELEMENT.get(tag_wo_ns, None)

    if read_as_sequence is None:
        raise DeserializationException(
            f"Expected the element tag to be a valid model type "
            f"of a concrete instance of 'DataElement', "
            f"but got tag {tag_wo_ns!r}"
        )

    return read_as_sequence(element, iterator)


class _ReaderAndSetterForProperty:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`Property`.

    The properties correspond to the constructor arguments of
    :py:class:`Property`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.extensions: Optional[List[aas_types.Extension]] = None
        self.category: Optional[str] = None
        self.id_short: Optional[str] = None
        self.display_name: Optional[List[aas_types.LangStringNameType]] = None
        self.description: Optional[List[aas_types.LangStringTextType]] = None
        self.semantic_id: Optional[aas_types.Reference] = None
        self.supplemental_semantic_ids: Optional[List[aas_types.Reference]] = None
        self.qualifiers: Optional[List[aas_types.Qualifier]] = None
        self.embedded_data_specifications: Optional[
            List[aas_types.EmbeddedDataSpecification]
        ] = None
        self.value_type: Optional[aas_types.DataTypeDefXSD] = None
        self.value: Optional[str] = None
        self.value_id: Optional[aas_types.Reference] = None

    def read_and_set_extensions(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Property.extensions` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Extension] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_extension_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.extensions = result

    def read_and_set_category(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Property.category` and set it.
        """
        self.category = _read_str_from_element_text(element, iterator)

    def read_and_set_id_short(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Property.id_short` and set it.
        """
        self.id_short = _read_str_from_element_text(element, iterator)

    def read_and_set_display_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Property.display_name` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringNameType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_name_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.display_name = result

    def read_and_set_description(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Property.description` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringTextType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_text_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.description = result

    def read_and_set_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Property.semantic_id` and set it.
        """
        self.semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_supplemental_semantic_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Property.supplemental_semantic_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.supplemental_semantic_ids = result

    def read_and_set_qualifiers(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Property.qualifiers` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Qualifier] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_qualifier_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.qualifiers = result

    def read_and_set_embedded_data_specifications(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Property.embedded_data_specifications` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.EmbeddedDataSpecification] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_embedded_data_specification_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.embedded_data_specifications = result

    def read_and_set_value_type(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Property.value_type` and set it.
        """
        self.value_type = _read_data_type_def_xsd_from_element_text(element, iterator)

    def read_and_set_value(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Property.value` and set it.
        """
        self.value = _read_str_from_element_text(element, iterator)

    def read_and_set_value_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Property.value_id` and set it.
        """
        self.value_id = _read_reference_as_sequence(element, iterator)


def _read_property_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Property:
    """
    Read an instance of :py:class:`.types.Property`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForProperty()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_PROPERTY.get(tag_wo_ns, None)
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.value_type is None:
        raise DeserializationException("The required property 'valueType' is missing")

    return aas_types.Property(
        reader_and_setter.value_type,
        reader_and_setter.extensions,
        reader_and_setter.category,
        reader_and_setter.id_short,
        reader_and_setter.display_name,
        reader_and_setter.description,
        reader_and_setter.semantic_id,
        reader_and_setter.supplemental_semantic_ids,
        reader_and_setter.qualifiers,
        reader_and_setter.embedded_data_specifications,
        reader_and_setter.value,
        reader_and_setter.value_id,
    )


def _read_property_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Property:
    """
    Read an instance of :py:class:`.types.Property` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "property":
        raise DeserializationException(
            f"Expected the element with the tag 'property', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_property_as_sequence(element, iterator)


class _ReaderAndSetterForMultiLanguageProperty:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`MultiLanguageProperty`.

    The properties correspond to the constructor arguments of
    :py:class:`MultiLanguageProperty`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.extensions: Optional[List[aas_types.Extension]] = None
        self.category: Optional[str] = None
        self.id_short: Optional[str] = None
        self.display_name: Optional[List[aas_types.LangStringNameType]] = None
        self.description: Optional[List[aas_types.LangStringTextType]] = None
        self.semantic_id: Optional[aas_types.Reference] = None
        self.supplemental_semantic_ids: Optional[List[aas_types.Reference]] = None
        self.qualifiers: Optional[List[aas_types.Qualifier]] = None
        self.embedded_data_specifications: Optional[
            List[aas_types.EmbeddedDataSpecification]
        ] = None
        self.value: Optional[List[aas_types.LangStringTextType]] = None
        self.value_id: Optional[aas_types.Reference] = None

    def read_and_set_extensions(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.MultiLanguageProperty.extensions` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Extension] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_extension_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.extensions = result

    def read_and_set_category(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.MultiLanguageProperty.category` and set it.
        """
        self.category = _read_str_from_element_text(element, iterator)

    def read_and_set_id_short(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.MultiLanguageProperty.id_short` and set it.
        """
        self.id_short = _read_str_from_element_text(element, iterator)

    def read_and_set_display_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.MultiLanguageProperty.display_name` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringNameType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_name_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.display_name = result

    def read_and_set_description(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.MultiLanguageProperty.description` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringTextType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_text_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.description = result

    def read_and_set_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.MultiLanguageProperty.semantic_id` and set it.
        """
        self.semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_supplemental_semantic_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.MultiLanguageProperty.supplemental_semantic_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.supplemental_semantic_ids = result

    def read_and_set_qualifiers(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.MultiLanguageProperty.qualifiers` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Qualifier] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_qualifier_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.qualifiers = result

    def read_and_set_embedded_data_specifications(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.MultiLanguageProperty.embedded_data_specifications` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.EmbeddedDataSpecification] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_embedded_data_specification_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.embedded_data_specifications = result

    def read_and_set_value(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.MultiLanguageProperty.value` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringTextType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_text_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.value = result

    def read_and_set_value_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.MultiLanguageProperty.value_id` and set it.
        """
        self.value_id = _read_reference_as_sequence(element, iterator)


def _read_multi_language_property_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.MultiLanguageProperty:
    """
    Read an instance of :py:class:`.types.MultiLanguageProperty`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForMultiLanguageProperty()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_MULTI_LANGUAGE_PROPERTY.get(
            tag_wo_ns, None
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    return aas_types.MultiLanguageProperty(
        reader_and_setter.extensions,
        reader_and_setter.category,
        reader_and_setter.id_short,
        reader_and_setter.display_name,
        reader_and_setter.description,
        reader_and_setter.semantic_id,
        reader_and_setter.supplemental_semantic_ids,
        reader_and_setter.qualifiers,
        reader_and_setter.embedded_data_specifications,
        reader_and_setter.value,
        reader_and_setter.value_id,
    )


def _read_multi_language_property_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.MultiLanguageProperty:
    """
    Read an instance of :py:class:`.types.MultiLanguageProperty` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "multiLanguageProperty":
        raise DeserializationException(
            f"Expected the element with the tag 'multiLanguageProperty', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_multi_language_property_as_sequence(element, iterator)


class _ReaderAndSetterForRange:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`Range`.

    The properties correspond to the constructor arguments of
    :py:class:`Range`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.extensions: Optional[List[aas_types.Extension]] = None
        self.category: Optional[str] = None
        self.id_short: Optional[str] = None
        self.display_name: Optional[List[aas_types.LangStringNameType]] = None
        self.description: Optional[List[aas_types.LangStringTextType]] = None
        self.semantic_id: Optional[aas_types.Reference] = None
        self.supplemental_semantic_ids: Optional[List[aas_types.Reference]] = None
        self.qualifiers: Optional[List[aas_types.Qualifier]] = None
        self.embedded_data_specifications: Optional[
            List[aas_types.EmbeddedDataSpecification]
        ] = None
        self.value_type: Optional[aas_types.DataTypeDefXSD] = None
        self.min: Optional[str] = None
        self.max: Optional[str] = None

    def read_and_set_extensions(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Range.extensions` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Extension] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_extension_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.extensions = result

    def read_and_set_category(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Range.category` and set it.
        """
        self.category = _read_str_from_element_text(element, iterator)

    def read_and_set_id_short(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Range.id_short` and set it.
        """
        self.id_short = _read_str_from_element_text(element, iterator)

    def read_and_set_display_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Range.display_name` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringNameType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_name_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.display_name = result

    def read_and_set_description(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Range.description` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringTextType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_text_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.description = result

    def read_and_set_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Range.semantic_id` and set it.
        """
        self.semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_supplemental_semantic_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Range.supplemental_semantic_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.supplemental_semantic_ids = result

    def read_and_set_qualifiers(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Range.qualifiers` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Qualifier] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_qualifier_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.qualifiers = result

    def read_and_set_embedded_data_specifications(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Range.embedded_data_specifications` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.EmbeddedDataSpecification] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_embedded_data_specification_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.embedded_data_specifications = result

    def read_and_set_value_type(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Range.value_type` and set it.
        """
        self.value_type = _read_data_type_def_xsd_from_element_text(element, iterator)

    def read_and_set_min(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Range.min` and set it.
        """
        self.min = _read_str_from_element_text(element, iterator)

    def read_and_set_max(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Range.max` and set it.
        """
        self.max = _read_str_from_element_text(element, iterator)


def _read_range_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Range:
    """
    Read an instance of :py:class:`.types.Range`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForRange()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_RANGE.get(tag_wo_ns, None)
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.value_type is None:
        raise DeserializationException("The required property 'valueType' is missing")

    return aas_types.Range(
        reader_and_setter.value_type,
        reader_and_setter.extensions,
        reader_and_setter.category,
        reader_and_setter.id_short,
        reader_and_setter.display_name,
        reader_and_setter.description,
        reader_and_setter.semantic_id,
        reader_and_setter.supplemental_semantic_ids,
        reader_and_setter.qualifiers,
        reader_and_setter.embedded_data_specifications,
        reader_and_setter.min,
        reader_and_setter.max,
    )


def _read_range_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Range:
    """
    Read an instance of :py:class:`.types.Range` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "range":
        raise DeserializationException(
            f"Expected the element with the tag 'range', " f"but got tag: {tag_wo_ns}"
        )

    return _read_range_as_sequence(element, iterator)


class _ReaderAndSetterForReferenceElement:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`ReferenceElement`.

    The properties correspond to the constructor arguments of
    :py:class:`ReferenceElement`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.extensions: Optional[List[aas_types.Extension]] = None
        self.category: Optional[str] = None
        self.id_short: Optional[str] = None
        self.display_name: Optional[List[aas_types.LangStringNameType]] = None
        self.description: Optional[List[aas_types.LangStringTextType]] = None
        self.semantic_id: Optional[aas_types.Reference] = None
        self.supplemental_semantic_ids: Optional[List[aas_types.Reference]] = None
        self.qualifiers: Optional[List[aas_types.Qualifier]] = None
        self.embedded_data_specifications: Optional[
            List[aas_types.EmbeddedDataSpecification]
        ] = None
        self.value: Optional[aas_types.Reference] = None

    def read_and_set_extensions(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ReferenceElement.extensions` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Extension] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_extension_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.extensions = result

    def read_and_set_category(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ReferenceElement.category` and set it.
        """
        self.category = _read_str_from_element_text(element, iterator)

    def read_and_set_id_short(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ReferenceElement.id_short` and set it.
        """
        self.id_short = _read_str_from_element_text(element, iterator)

    def read_and_set_display_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ReferenceElement.display_name` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringNameType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_name_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.display_name = result

    def read_and_set_description(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ReferenceElement.description` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringTextType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_text_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.description = result

    def read_and_set_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ReferenceElement.semantic_id` and set it.
        """
        self.semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_supplemental_semantic_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ReferenceElement.supplemental_semantic_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.supplemental_semantic_ids = result

    def read_and_set_qualifiers(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ReferenceElement.qualifiers` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Qualifier] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_qualifier_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.qualifiers = result

    def read_and_set_embedded_data_specifications(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ReferenceElement.embedded_data_specifications` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.EmbeddedDataSpecification] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_embedded_data_specification_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.embedded_data_specifications = result

    def read_and_set_value(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ReferenceElement.value` and set it.
        """
        self.value = _read_reference_as_sequence(element, iterator)


def _read_reference_element_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.ReferenceElement:
    """
    Read an instance of :py:class:`.types.ReferenceElement`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForReferenceElement()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_REFERENCE_ELEMENT.get(
            tag_wo_ns, None
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    return aas_types.ReferenceElement(
        reader_and_setter.extensions,
        reader_and_setter.category,
        reader_and_setter.id_short,
        reader_and_setter.display_name,
        reader_and_setter.description,
        reader_and_setter.semantic_id,
        reader_and_setter.supplemental_semantic_ids,
        reader_and_setter.qualifiers,
        reader_and_setter.embedded_data_specifications,
        reader_and_setter.value,
    )


def _read_reference_element_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.ReferenceElement:
    """
    Read an instance of :py:class:`.types.ReferenceElement` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "referenceElement":
        raise DeserializationException(
            f"Expected the element with the tag 'referenceElement', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_reference_element_as_sequence(element, iterator)


class _ReaderAndSetterForBlob:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`Blob`.

    The properties correspond to the constructor arguments of
    :py:class:`Blob`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.extensions: Optional[List[aas_types.Extension]] = None
        self.category: Optional[str] = None
        self.id_short: Optional[str] = None
        self.display_name: Optional[List[aas_types.LangStringNameType]] = None
        self.description: Optional[List[aas_types.LangStringTextType]] = None
        self.semantic_id: Optional[aas_types.Reference] = None
        self.supplemental_semantic_ids: Optional[List[aas_types.Reference]] = None
        self.qualifiers: Optional[List[aas_types.Qualifier]] = None
        self.embedded_data_specifications: Optional[
            List[aas_types.EmbeddedDataSpecification]
        ] = None
        self.value: Optional[bytes] = None
        self.content_type: Optional[str] = None

    def read_and_set_extensions(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Blob.extensions` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Extension] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_extension_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.extensions = result

    def read_and_set_category(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Blob.category` and set it.
        """
        self.category = _read_str_from_element_text(element, iterator)

    def read_and_set_id_short(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Blob.id_short` and set it.
        """
        self.id_short = _read_str_from_element_text(element, iterator)

    def read_and_set_display_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Blob.display_name` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringNameType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_name_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.display_name = result

    def read_and_set_description(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Blob.description` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringTextType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_text_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.description = result

    def read_and_set_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Blob.semantic_id` and set it.
        """
        self.semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_supplemental_semantic_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Blob.supplemental_semantic_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.supplemental_semantic_ids = result

    def read_and_set_qualifiers(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Blob.qualifiers` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Qualifier] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_qualifier_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.qualifiers = result

    def read_and_set_embedded_data_specifications(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Blob.embedded_data_specifications` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.EmbeddedDataSpecification] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_embedded_data_specification_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.embedded_data_specifications = result

    def read_and_set_value(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Blob.value` and set it.
        """
        self.value = _read_bytes_from_element_text(element, iterator)

    def read_and_set_content_type(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Blob.content_type` and set it.
        """
        self.content_type = _read_str_from_element_text(element, iterator)


def _read_blob_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Blob:
    """
    Read an instance of :py:class:`.types.Blob`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForBlob()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_BLOB.get(tag_wo_ns, None)
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.content_type is None:
        raise DeserializationException("The required property 'contentType' is missing")

    return aas_types.Blob(
        reader_and_setter.content_type,
        reader_and_setter.extensions,
        reader_and_setter.category,
        reader_and_setter.id_short,
        reader_and_setter.display_name,
        reader_and_setter.description,
        reader_and_setter.semantic_id,
        reader_and_setter.supplemental_semantic_ids,
        reader_and_setter.qualifiers,
        reader_and_setter.embedded_data_specifications,
        reader_and_setter.value,
    )


def _read_blob_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Blob:
    """
    Read an instance of :py:class:`.types.Blob` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "blob":
        raise DeserializationException(
            f"Expected the element with the tag 'blob', " f"but got tag: {tag_wo_ns}"
        )

    return _read_blob_as_sequence(element, iterator)


class _ReaderAndSetterForFile:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`File`.

    The properties correspond to the constructor arguments of
    :py:class:`File`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.extensions: Optional[List[aas_types.Extension]] = None
        self.category: Optional[str] = None
        self.id_short: Optional[str] = None
        self.display_name: Optional[List[aas_types.LangStringNameType]] = None
        self.description: Optional[List[aas_types.LangStringTextType]] = None
        self.semantic_id: Optional[aas_types.Reference] = None
        self.supplemental_semantic_ids: Optional[List[aas_types.Reference]] = None
        self.qualifiers: Optional[List[aas_types.Qualifier]] = None
        self.embedded_data_specifications: Optional[
            List[aas_types.EmbeddedDataSpecification]
        ] = None
        self.value: Optional[str] = None
        self.content_type: Optional[str] = None

    def read_and_set_extensions(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.File.extensions` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Extension] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_extension_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.extensions = result

    def read_and_set_category(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.File.category` and set it.
        """
        self.category = _read_str_from_element_text(element, iterator)

    def read_and_set_id_short(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.File.id_short` and set it.
        """
        self.id_short = _read_str_from_element_text(element, iterator)

    def read_and_set_display_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.File.display_name` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringNameType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_name_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.display_name = result

    def read_and_set_description(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.File.description` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringTextType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_text_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.description = result

    def read_and_set_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.File.semantic_id` and set it.
        """
        self.semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_supplemental_semantic_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.File.supplemental_semantic_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.supplemental_semantic_ids = result

    def read_and_set_qualifiers(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.File.qualifiers` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Qualifier] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_qualifier_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.qualifiers = result

    def read_and_set_embedded_data_specifications(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.File.embedded_data_specifications` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.EmbeddedDataSpecification] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_embedded_data_specification_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.embedded_data_specifications = result

    def read_and_set_value(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.File.value` and set it.
        """
        self.value = _read_str_from_element_text(element, iterator)

    def read_and_set_content_type(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.File.content_type` and set it.
        """
        self.content_type = _read_str_from_element_text(element, iterator)


def _read_file_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.File:
    """
    Read an instance of :py:class:`.types.File`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForFile()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_FILE.get(tag_wo_ns, None)
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.content_type is None:
        raise DeserializationException("The required property 'contentType' is missing")

    return aas_types.File(
        reader_and_setter.content_type,
        reader_and_setter.extensions,
        reader_and_setter.category,
        reader_and_setter.id_short,
        reader_and_setter.display_name,
        reader_and_setter.description,
        reader_and_setter.semantic_id,
        reader_and_setter.supplemental_semantic_ids,
        reader_and_setter.qualifiers,
        reader_and_setter.embedded_data_specifications,
        reader_and_setter.value,
    )


def _read_file_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.File:
    """
    Read an instance of :py:class:`.types.File` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "file":
        raise DeserializationException(
            f"Expected the element with the tag 'file', " f"but got tag: {tag_wo_ns}"
        )

    return _read_file_as_sequence(element, iterator)


class _ReaderAndSetterForAnnotatedRelationshipElement:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`AnnotatedRelationshipElement`.

    The properties correspond to the constructor arguments of
    :py:class:`AnnotatedRelationshipElement`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.extensions: Optional[List[aas_types.Extension]] = None
        self.category: Optional[str] = None
        self.id_short: Optional[str] = None
        self.display_name: Optional[List[aas_types.LangStringNameType]] = None
        self.description: Optional[List[aas_types.LangStringTextType]] = None
        self.semantic_id: Optional[aas_types.Reference] = None
        self.supplemental_semantic_ids: Optional[List[aas_types.Reference]] = None
        self.qualifiers: Optional[List[aas_types.Qualifier]] = None
        self.embedded_data_specifications: Optional[
            List[aas_types.EmbeddedDataSpecification]
        ] = None
        self.first: Optional[aas_types.Reference] = None
        self.second: Optional[aas_types.Reference] = None
        self.annotations: Optional[List[aas_types.DataElement]] = None

    def read_and_set_extensions(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AnnotatedRelationshipElement.extensions` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Extension] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_extension_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.extensions = result

    def read_and_set_category(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AnnotatedRelationshipElement.category` and set it.
        """
        self.category = _read_str_from_element_text(element, iterator)

    def read_and_set_id_short(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AnnotatedRelationshipElement.id_short` and set it.
        """
        self.id_short = _read_str_from_element_text(element, iterator)

    def read_and_set_display_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AnnotatedRelationshipElement.display_name` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringNameType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_name_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.display_name = result

    def read_and_set_description(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AnnotatedRelationshipElement.description` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringTextType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_text_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.description = result

    def read_and_set_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AnnotatedRelationshipElement.semantic_id` and set it.
        """
        self.semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_supplemental_semantic_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AnnotatedRelationshipElement.supplemental_semantic_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.supplemental_semantic_ids = result

    def read_and_set_qualifiers(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AnnotatedRelationshipElement.qualifiers` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Qualifier] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_qualifier_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.qualifiers = result

    def read_and_set_embedded_data_specifications(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AnnotatedRelationshipElement.embedded_data_specifications` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.EmbeddedDataSpecification] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_embedded_data_specification_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.embedded_data_specifications = result

    def read_and_set_first(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AnnotatedRelationshipElement.first` and set it.
        """
        self.first = _read_reference_as_sequence(element, iterator)

    def read_and_set_second(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AnnotatedRelationshipElement.second` and set it.
        """
        self.second = _read_reference_as_sequence(element, iterator)

    def read_and_set_annotations(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.AnnotatedRelationshipElement.annotations` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.DataElement] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_data_element_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.annotations = result


def _read_annotated_relationship_element_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.AnnotatedRelationshipElement:
    """
    Read an instance of :py:class:`.types.AnnotatedRelationshipElement`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForAnnotatedRelationshipElement()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = (
            _READ_AND_SET_DISPATCH_FOR_ANNOTATED_RELATIONSHIP_ELEMENT.get(
                tag_wo_ns, None
            )
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.first is None:
        raise DeserializationException("The required property 'first' is missing")

    if reader_and_setter.second is None:
        raise DeserializationException("The required property 'second' is missing")

    return aas_types.AnnotatedRelationshipElement(
        reader_and_setter.first,
        reader_and_setter.second,
        reader_and_setter.extensions,
        reader_and_setter.category,
        reader_and_setter.id_short,
        reader_and_setter.display_name,
        reader_and_setter.description,
        reader_and_setter.semantic_id,
        reader_and_setter.supplemental_semantic_ids,
        reader_and_setter.qualifiers,
        reader_and_setter.embedded_data_specifications,
        reader_and_setter.annotations,
    )


def _read_annotated_relationship_element_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.AnnotatedRelationshipElement:
    """
    Read an instance of :py:class:`.types.AnnotatedRelationshipElement` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "annotatedRelationshipElement":
        raise DeserializationException(
            f"Expected the element with the tag 'annotatedRelationshipElement', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_annotated_relationship_element_as_sequence(element, iterator)


class _ReaderAndSetterForEntity:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`Entity`.

    The properties correspond to the constructor arguments of
    :py:class:`Entity`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.extensions: Optional[List[aas_types.Extension]] = None
        self.category: Optional[str] = None
        self.id_short: Optional[str] = None
        self.display_name: Optional[List[aas_types.LangStringNameType]] = None
        self.description: Optional[List[aas_types.LangStringTextType]] = None
        self.semantic_id: Optional[aas_types.Reference] = None
        self.supplemental_semantic_ids: Optional[List[aas_types.Reference]] = None
        self.qualifiers: Optional[List[aas_types.Qualifier]] = None
        self.embedded_data_specifications: Optional[
            List[aas_types.EmbeddedDataSpecification]
        ] = None
        self.statements: Optional[List[aas_types.SubmodelElement]] = None
        self.entity_type: Optional[aas_types.EntityType] = None
        self.global_asset_id: Optional[str] = None
        self.specific_asset_ids: Optional[List[aas_types.SpecificAssetID]] = None

    def read_and_set_extensions(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Entity.extensions` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Extension] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_extension_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.extensions = result

    def read_and_set_category(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Entity.category` and set it.
        """
        self.category = _read_str_from_element_text(element, iterator)

    def read_and_set_id_short(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Entity.id_short` and set it.
        """
        self.id_short = _read_str_from_element_text(element, iterator)

    def read_and_set_display_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Entity.display_name` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringNameType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_name_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.display_name = result

    def read_and_set_description(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Entity.description` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringTextType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_text_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.description = result

    def read_and_set_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Entity.semantic_id` and set it.
        """
        self.semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_supplemental_semantic_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Entity.supplemental_semantic_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.supplemental_semantic_ids = result

    def read_and_set_qualifiers(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Entity.qualifiers` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Qualifier] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_qualifier_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.qualifiers = result

    def read_and_set_embedded_data_specifications(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Entity.embedded_data_specifications` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.EmbeddedDataSpecification] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_embedded_data_specification_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.embedded_data_specifications = result

    def read_and_set_statements(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Entity.statements` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.SubmodelElement] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_submodel_element_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.statements = result

    def read_and_set_entity_type(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Entity.entity_type` and set it.
        """
        self.entity_type = _read_entity_type_from_element_text(element, iterator)

    def read_and_set_global_asset_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Entity.global_asset_id` and set it.
        """
        self.global_asset_id = _read_str_from_element_text(element, iterator)

    def read_and_set_specific_asset_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Entity.specific_asset_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.SpecificAssetID] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_specific_asset_id_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.specific_asset_ids = result


def _read_entity_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Entity:
    """
    Read an instance of :py:class:`.types.Entity`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForEntity()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_ENTITY.get(tag_wo_ns, None)
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.entity_type is None:
        raise DeserializationException("The required property 'entityType' is missing")

    return aas_types.Entity(
        reader_and_setter.entity_type,
        reader_and_setter.extensions,
        reader_and_setter.category,
        reader_and_setter.id_short,
        reader_and_setter.display_name,
        reader_and_setter.description,
        reader_and_setter.semantic_id,
        reader_and_setter.supplemental_semantic_ids,
        reader_and_setter.qualifiers,
        reader_and_setter.embedded_data_specifications,
        reader_and_setter.statements,
        reader_and_setter.global_asset_id,
        reader_and_setter.specific_asset_ids,
    )


def _read_entity_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Entity:
    """
    Read an instance of :py:class:`.types.Entity` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "entity":
        raise DeserializationException(
            f"Expected the element with the tag 'entity', " f"but got tag: {tag_wo_ns}"
        )

    return _read_entity_as_sequence(element, iterator)


def _read_entity_type_from_element_text(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.EntityType:
    """
    Parse the text of :paramref:`element` as a literal of
    :py:class:`.types.EntityType`, and read the corresponding
    end element from :paramref:`iterator`.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed value
    """
    text = _read_text_from_element(element, iterator)

    literal = aas_stringification.entity_type_from_str(text)
    if literal is None:
        raise DeserializationException(
            f"Not a valid string representation of " f"a literal of EntityType: {text}"
        )

    return literal


def _read_direction_from_element_text(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Direction:
    """
    Parse the text of :paramref:`element` as a literal of
    :py:class:`.types.Direction`, and read the corresponding
    end element from :paramref:`iterator`.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed value
    """
    text = _read_text_from_element(element, iterator)

    literal = aas_stringification.direction_from_str(text)
    if literal is None:
        raise DeserializationException(
            f"Not a valid string representation of " f"a literal of Direction: {text}"
        )

    return literal


def _read_state_of_event_from_element_text(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.StateOfEvent:
    """
    Parse the text of :paramref:`element` as a literal of
    :py:class:`.types.StateOfEvent`, and read the corresponding
    end element from :paramref:`iterator`.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed value
    """
    text = _read_text_from_element(element, iterator)

    literal = aas_stringification.state_of_event_from_str(text)
    if literal is None:
        raise DeserializationException(
            f"Not a valid string representation of "
            f"a literal of StateOfEvent: {text}"
        )

    return literal


class _ReaderAndSetterForEventPayload:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`EventPayload`.

    The properties correspond to the constructor arguments of
    :py:class:`EventPayload`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.source: Optional[aas_types.Reference] = None
        self.source_semantic_id: Optional[aas_types.Reference] = None
        self.observable_reference: Optional[aas_types.Reference] = None
        self.observable_semantic_id: Optional[aas_types.Reference] = None
        self.topic: Optional[str] = None
        self.subject_id: Optional[aas_types.Reference] = None
        self.time_stamp: Optional[str] = None
        self.payload: Optional[bytes] = None

    def read_and_set_source(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.EventPayload.source` and set it.
        """
        self.source = _read_reference_as_sequence(element, iterator)

    def read_and_set_source_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.EventPayload.source_semantic_id` and set it.
        """
        self.source_semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_observable_reference(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.EventPayload.observable_reference` and set it.
        """
        self.observable_reference = _read_reference_as_sequence(element, iterator)

    def read_and_set_observable_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.EventPayload.observable_semantic_id` and set it.
        """
        self.observable_semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_topic(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.EventPayload.topic` and set it.
        """
        self.topic = _read_str_from_element_text(element, iterator)

    def read_and_set_subject_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.EventPayload.subject_id` and set it.
        """
        self.subject_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_time_stamp(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.EventPayload.time_stamp` and set it.
        """
        self.time_stamp = _read_str_from_element_text(element, iterator)

    def read_and_set_payload(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.EventPayload.payload` and set it.
        """
        self.payload = _read_bytes_from_element_text(element, iterator)


def _read_event_payload_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.EventPayload:
    """
    Read an instance of :py:class:`.types.EventPayload`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForEventPayload()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_EVENT_PAYLOAD.get(
            tag_wo_ns, None
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.source is None:
        raise DeserializationException("The required property 'source' is missing")

    if reader_and_setter.observable_reference is None:
        raise DeserializationException(
            "The required property 'observableReference' is missing"
        )

    if reader_and_setter.time_stamp is None:
        raise DeserializationException("The required property 'timeStamp' is missing")

    return aas_types.EventPayload(
        reader_and_setter.source,
        reader_and_setter.observable_reference,
        reader_and_setter.time_stamp,
        reader_and_setter.source_semantic_id,
        reader_and_setter.observable_semantic_id,
        reader_and_setter.topic,
        reader_and_setter.subject_id,
        reader_and_setter.payload,
    )


def _read_event_payload_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.EventPayload:
    """
    Read an instance of :py:class:`.types.EventPayload` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "eventPayload":
        raise DeserializationException(
            f"Expected the element with the tag 'eventPayload', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_event_payload_as_sequence(element, iterator)


def _read_event_element_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.EventElement:
    """
    Read an instance of :py:class:`.types.EventElement` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)
    read_as_sequence = _DISPATCH_FOR_EVENT_ELEMENT.get(tag_wo_ns, None)

    if read_as_sequence is None:
        raise DeserializationException(
            f"Expected the element tag to be a valid model type "
            f"of a concrete instance of 'EventElement', "
            f"but got tag {tag_wo_ns!r}"
        )

    return read_as_sequence(element, iterator)


class _ReaderAndSetterForBasicEventElement:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`BasicEventElement`.

    The properties correspond to the constructor arguments of
    :py:class:`BasicEventElement`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.extensions: Optional[List[aas_types.Extension]] = None
        self.category: Optional[str] = None
        self.id_short: Optional[str] = None
        self.display_name: Optional[List[aas_types.LangStringNameType]] = None
        self.description: Optional[List[aas_types.LangStringTextType]] = None
        self.semantic_id: Optional[aas_types.Reference] = None
        self.supplemental_semantic_ids: Optional[List[aas_types.Reference]] = None
        self.qualifiers: Optional[List[aas_types.Qualifier]] = None
        self.embedded_data_specifications: Optional[
            List[aas_types.EmbeddedDataSpecification]
        ] = None
        self.observed: Optional[aas_types.Reference] = None
        self.direction: Optional[aas_types.Direction] = None
        self.state: Optional[aas_types.StateOfEvent] = None
        self.message_topic: Optional[str] = None
        self.message_broker: Optional[aas_types.Reference] = None
        self.last_update: Optional[str] = None
        self.min_interval: Optional[str] = None
        self.max_interval: Optional[str] = None

    def read_and_set_extensions(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.BasicEventElement.extensions` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Extension] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_extension_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.extensions = result

    def read_and_set_category(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.BasicEventElement.category` and set it.
        """
        self.category = _read_str_from_element_text(element, iterator)

    def read_and_set_id_short(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.BasicEventElement.id_short` and set it.
        """
        self.id_short = _read_str_from_element_text(element, iterator)

    def read_and_set_display_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.BasicEventElement.display_name` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringNameType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_name_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.display_name = result

    def read_and_set_description(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.BasicEventElement.description` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringTextType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_text_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.description = result

    def read_and_set_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.BasicEventElement.semantic_id` and set it.
        """
        self.semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_supplemental_semantic_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.BasicEventElement.supplemental_semantic_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.supplemental_semantic_ids = result

    def read_and_set_qualifiers(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.BasicEventElement.qualifiers` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Qualifier] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_qualifier_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.qualifiers = result

    def read_and_set_embedded_data_specifications(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.BasicEventElement.embedded_data_specifications` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.EmbeddedDataSpecification] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_embedded_data_specification_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.embedded_data_specifications = result

    def read_and_set_observed(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.BasicEventElement.observed` and set it.
        """
        self.observed = _read_reference_as_sequence(element, iterator)

    def read_and_set_direction(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.BasicEventElement.direction` and set it.
        """
        self.direction = _read_direction_from_element_text(element, iterator)

    def read_and_set_state(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.BasicEventElement.state` and set it.
        """
        self.state = _read_state_of_event_from_element_text(element, iterator)

    def read_and_set_message_topic(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.BasicEventElement.message_topic` and set it.
        """
        self.message_topic = _read_str_from_element_text(element, iterator)

    def read_and_set_message_broker(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.BasicEventElement.message_broker` and set it.
        """
        self.message_broker = _read_reference_as_sequence(element, iterator)

    def read_and_set_last_update(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.BasicEventElement.last_update` and set it.
        """
        self.last_update = _read_str_from_element_text(element, iterator)

    def read_and_set_min_interval(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.BasicEventElement.min_interval` and set it.
        """
        self.min_interval = _read_str_from_element_text(element, iterator)

    def read_and_set_max_interval(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.BasicEventElement.max_interval` and set it.
        """
        self.max_interval = _read_str_from_element_text(element, iterator)


def _read_basic_event_element_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.BasicEventElement:
    """
    Read an instance of :py:class:`.types.BasicEventElement`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForBasicEventElement()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_BASIC_EVENT_ELEMENT.get(
            tag_wo_ns, None
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.observed is None:
        raise DeserializationException("The required property 'observed' is missing")

    if reader_and_setter.direction is None:
        raise DeserializationException("The required property 'direction' is missing")

    if reader_and_setter.state is None:
        raise DeserializationException("The required property 'state' is missing")

    return aas_types.BasicEventElement(
        reader_and_setter.observed,
        reader_and_setter.direction,
        reader_and_setter.state,
        reader_and_setter.extensions,
        reader_and_setter.category,
        reader_and_setter.id_short,
        reader_and_setter.display_name,
        reader_and_setter.description,
        reader_and_setter.semantic_id,
        reader_and_setter.supplemental_semantic_ids,
        reader_and_setter.qualifiers,
        reader_and_setter.embedded_data_specifications,
        reader_and_setter.message_topic,
        reader_and_setter.message_broker,
        reader_and_setter.last_update,
        reader_and_setter.min_interval,
        reader_and_setter.max_interval,
    )


def _read_basic_event_element_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.BasicEventElement:
    """
    Read an instance of :py:class:`.types.BasicEventElement` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "basicEventElement":
        raise DeserializationException(
            f"Expected the element with the tag 'basicEventElement', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_basic_event_element_as_sequence(element, iterator)


class _ReaderAndSetterForOperation:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`Operation`.

    The properties correspond to the constructor arguments of
    :py:class:`Operation`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.extensions: Optional[List[aas_types.Extension]] = None
        self.category: Optional[str] = None
        self.id_short: Optional[str] = None
        self.display_name: Optional[List[aas_types.LangStringNameType]] = None
        self.description: Optional[List[aas_types.LangStringTextType]] = None
        self.semantic_id: Optional[aas_types.Reference] = None
        self.supplemental_semantic_ids: Optional[List[aas_types.Reference]] = None
        self.qualifiers: Optional[List[aas_types.Qualifier]] = None
        self.embedded_data_specifications: Optional[
            List[aas_types.EmbeddedDataSpecification]
        ] = None
        self.input_variables: Optional[List[aas_types.OperationVariable]] = None
        self.output_variables: Optional[List[aas_types.OperationVariable]] = None
        self.inoutput_variables: Optional[List[aas_types.OperationVariable]] = None

    def read_and_set_extensions(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Operation.extensions` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Extension] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_extension_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.extensions = result

    def read_and_set_category(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Operation.category` and set it.
        """
        self.category = _read_str_from_element_text(element, iterator)

    def read_and_set_id_short(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Operation.id_short` and set it.
        """
        self.id_short = _read_str_from_element_text(element, iterator)

    def read_and_set_display_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Operation.display_name` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringNameType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_name_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.display_name = result

    def read_and_set_description(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Operation.description` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringTextType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_text_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.description = result

    def read_and_set_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Operation.semantic_id` and set it.
        """
        self.semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_supplemental_semantic_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Operation.supplemental_semantic_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.supplemental_semantic_ids = result

    def read_and_set_qualifiers(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Operation.qualifiers` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Qualifier] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_qualifier_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.qualifiers = result

    def read_and_set_embedded_data_specifications(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Operation.embedded_data_specifications` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.EmbeddedDataSpecification] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_embedded_data_specification_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.embedded_data_specifications = result

    def read_and_set_input_variables(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Operation.input_variables` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.OperationVariable] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_operation_variable_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.input_variables = result

    def read_and_set_output_variables(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Operation.output_variables` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.OperationVariable] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_operation_variable_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.output_variables = result

    def read_and_set_inoutput_variables(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Operation.inoutput_variables` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.OperationVariable] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_operation_variable_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.inoutput_variables = result


def _read_operation_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Operation:
    """
    Read an instance of :py:class:`.types.Operation`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForOperation()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_OPERATION.get(tag_wo_ns, None)
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    return aas_types.Operation(
        reader_and_setter.extensions,
        reader_and_setter.category,
        reader_and_setter.id_short,
        reader_and_setter.display_name,
        reader_and_setter.description,
        reader_and_setter.semantic_id,
        reader_and_setter.supplemental_semantic_ids,
        reader_and_setter.qualifiers,
        reader_and_setter.embedded_data_specifications,
        reader_and_setter.input_variables,
        reader_and_setter.output_variables,
        reader_and_setter.inoutput_variables,
    )


def _read_operation_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Operation:
    """
    Read an instance of :py:class:`.types.Operation` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "operation":
        raise DeserializationException(
            f"Expected the element with the tag 'operation', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_operation_as_sequence(element, iterator)


class _ReaderAndSetterForOperationVariable:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`OperationVariable`.

    The properties correspond to the constructor arguments of
    :py:class:`OperationVariable`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.value: Optional[aas_types.SubmodelElement] = None

    def read_and_set_value(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.OperationVariable.value` and set it.
        """
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected a discriminator start element corresponding "
                "to SubmodelElement, but got end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event != "start":
            raise DeserializationException(
                f"Expected a discriminator start element corresponding "
                f"to SubmodelElement, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            result = _read_submodel_element_as_element(next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        _read_end_element(element, iterator)

        self.value = result


def _read_operation_variable_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.OperationVariable:
    """
    Read an instance of :py:class:`.types.OperationVariable`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForOperationVariable()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_OPERATION_VARIABLE.get(
            tag_wo_ns, None
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.value is None:
        raise DeserializationException("The required property 'value' is missing")

    return aas_types.OperationVariable(reader_and_setter.value)


def _read_operation_variable_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.OperationVariable:
    """
    Read an instance of :py:class:`.types.OperationVariable` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "operationVariable":
        raise DeserializationException(
            f"Expected the element with the tag 'operationVariable', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_operation_variable_as_sequence(element, iterator)


class _ReaderAndSetterForCapability:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`Capability`.

    The properties correspond to the constructor arguments of
    :py:class:`Capability`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.extensions: Optional[List[aas_types.Extension]] = None
        self.category: Optional[str] = None
        self.id_short: Optional[str] = None
        self.display_name: Optional[List[aas_types.LangStringNameType]] = None
        self.description: Optional[List[aas_types.LangStringTextType]] = None
        self.semantic_id: Optional[aas_types.Reference] = None
        self.supplemental_semantic_ids: Optional[List[aas_types.Reference]] = None
        self.qualifiers: Optional[List[aas_types.Qualifier]] = None
        self.embedded_data_specifications: Optional[
            List[aas_types.EmbeddedDataSpecification]
        ] = None

    def read_and_set_extensions(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Capability.extensions` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Extension] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_extension_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.extensions = result

    def read_and_set_category(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Capability.category` and set it.
        """
        self.category = _read_str_from_element_text(element, iterator)

    def read_and_set_id_short(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Capability.id_short` and set it.
        """
        self.id_short = _read_str_from_element_text(element, iterator)

    def read_and_set_display_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Capability.display_name` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringNameType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_name_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.display_name = result

    def read_and_set_description(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Capability.description` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringTextType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_text_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.description = result

    def read_and_set_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Capability.semantic_id` and set it.
        """
        self.semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_supplemental_semantic_ids(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Capability.supplemental_semantic_ids` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.supplemental_semantic_ids = result

    def read_and_set_qualifiers(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Capability.qualifiers` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Qualifier] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_qualifier_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.qualifiers = result

    def read_and_set_embedded_data_specifications(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Capability.embedded_data_specifications` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.EmbeddedDataSpecification] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_embedded_data_specification_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.embedded_data_specifications = result


def _read_capability_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Capability:
    """
    Read an instance of :py:class:`.types.Capability`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForCapability()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_CAPABILITY.get(tag_wo_ns, None)
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    return aas_types.Capability(
        reader_and_setter.extensions,
        reader_and_setter.category,
        reader_and_setter.id_short,
        reader_and_setter.display_name,
        reader_and_setter.description,
        reader_and_setter.semantic_id,
        reader_and_setter.supplemental_semantic_ids,
        reader_and_setter.qualifiers,
        reader_and_setter.embedded_data_specifications,
    )


def _read_capability_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Capability:
    """
    Read an instance of :py:class:`.types.Capability` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "capability":
        raise DeserializationException(
            f"Expected the element with the tag 'capability', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_capability_as_sequence(element, iterator)


class _ReaderAndSetterForConceptDescription:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`ConceptDescription`.

    The properties correspond to the constructor arguments of
    :py:class:`ConceptDescription`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.extensions: Optional[List[aas_types.Extension]] = None
        self.category: Optional[str] = None
        self.id_short: Optional[str] = None
        self.display_name: Optional[List[aas_types.LangStringNameType]] = None
        self.description: Optional[List[aas_types.LangStringTextType]] = None
        self.administration: Optional[aas_types.AdministrativeInformation] = None
        self.id: Optional[str] = None
        self.embedded_data_specifications: Optional[
            List[aas_types.EmbeddedDataSpecification]
        ] = None
        self.is_case_of: Optional[List[aas_types.Reference]] = None

    def read_and_set_extensions(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ConceptDescription.extensions` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Extension] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_extension_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.extensions = result

    def read_and_set_category(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ConceptDescription.category` and set it.
        """
        self.category = _read_str_from_element_text(element, iterator)

    def read_and_set_id_short(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ConceptDescription.id_short` and set it.
        """
        self.id_short = _read_str_from_element_text(element, iterator)

    def read_and_set_display_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ConceptDescription.display_name` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringNameType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_name_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.display_name = result

    def read_and_set_description(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ConceptDescription.description` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringTextType] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_text_type_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.description = result

    def read_and_set_administration(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ConceptDescription.administration` and set it.
        """
        self.administration = _read_administrative_information_as_sequence(
            element, iterator
        )

    def read_and_set_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ConceptDescription.id` and set it.
        """
        self.id = _read_str_from_element_text(element, iterator)

    def read_and_set_embedded_data_specifications(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ConceptDescription.embedded_data_specifications` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.EmbeddedDataSpecification] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_embedded_data_specification_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.embedded_data_specifications = result

    def read_and_set_is_case_of(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ConceptDescription.is_case_of` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Reference] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_reference_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.is_case_of = result


def _read_concept_description_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.ConceptDescription:
    """
    Read an instance of :py:class:`.types.ConceptDescription`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForConceptDescription()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_CONCEPT_DESCRIPTION.get(
            tag_wo_ns, None
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.id is None:
        raise DeserializationException("The required property 'id' is missing")

    return aas_types.ConceptDescription(
        reader_and_setter.id,
        reader_and_setter.extensions,
        reader_and_setter.category,
        reader_and_setter.id_short,
        reader_and_setter.display_name,
        reader_and_setter.description,
        reader_and_setter.administration,
        reader_and_setter.embedded_data_specifications,
        reader_and_setter.is_case_of,
    )


def _read_concept_description_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.ConceptDescription:
    """
    Read an instance of :py:class:`.types.ConceptDescription` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "conceptDescription":
        raise DeserializationException(
            f"Expected the element with the tag 'conceptDescription', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_concept_description_as_sequence(element, iterator)


def _read_reference_types_from_element_text(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.ReferenceTypes:
    """
    Parse the text of :paramref:`element` as a literal of
    :py:class:`.types.ReferenceTypes`, and read the corresponding
    end element from :paramref:`iterator`.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed value
    """
    text = _read_text_from_element(element, iterator)

    literal = aas_stringification.reference_types_from_str(text)
    if literal is None:
        raise DeserializationException(
            f"Not a valid string representation of "
            f"a literal of ReferenceTypes: {text}"
        )

    return literal


class _ReaderAndSetterForReference:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`Reference`.

    The properties correspond to the constructor arguments of
    :py:class:`Reference`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.type: Optional[aas_types.ReferenceTypes] = None
        self.referred_semantic_id: Optional[aas_types.Reference] = None
        self.keys: Optional[List[aas_types.Key]] = None

    def read_and_set_type(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Reference.type` and set it.
        """
        self.type = _read_reference_types_from_element_text(element, iterator)

    def read_and_set_referred_semantic_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Reference.referred_semantic_id` and set it.
        """
        self.referred_semantic_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_keys(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Reference.keys` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Key] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_key_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.keys = result


def _read_reference_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Reference:
    """
    Read an instance of :py:class:`.types.Reference`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForReference()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_REFERENCE.get(tag_wo_ns, None)
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.type is None:
        raise DeserializationException("The required property 'type' is missing")

    if reader_and_setter.keys is None:
        raise DeserializationException("The required property 'keys' is missing")

    return aas_types.Reference(
        reader_and_setter.type,
        reader_and_setter.keys,
        reader_and_setter.referred_semantic_id,
    )


def _read_reference_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Reference:
    """
    Read an instance of :py:class:`.types.Reference` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "reference":
        raise DeserializationException(
            f"Expected the element with the tag 'reference', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_reference_as_sequence(element, iterator)


class _ReaderAndSetterForKey:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`Key`.

    The properties correspond to the constructor arguments of
    :py:class:`Key`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.type: Optional[aas_types.KeyTypes] = None
        self.value: Optional[str] = None

    def read_and_set_type(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Key.type` and set it.
        """
        self.type = _read_key_types_from_element_text(element, iterator)

    def read_and_set_value(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Key.value` and set it.
        """
        self.value = _read_str_from_element_text(element, iterator)


def _read_key_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Key:
    """
    Read an instance of :py:class:`.types.Key`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForKey()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_KEY.get(tag_wo_ns, None)
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.type is None:
        raise DeserializationException("The required property 'type' is missing")

    if reader_and_setter.value is None:
        raise DeserializationException("The required property 'value' is missing")

    return aas_types.Key(reader_and_setter.type, reader_and_setter.value)


def _read_key_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Key:
    """
    Read an instance of :py:class:`.types.Key` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "key":
        raise DeserializationException(
            f"Expected the element with the tag 'key', " f"but got tag: {tag_wo_ns}"
        )

    return _read_key_as_sequence(element, iterator)


def _read_key_types_from_element_text(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.KeyTypes:
    """
    Parse the text of :paramref:`element` as a literal of
    :py:class:`.types.KeyTypes`, and read the corresponding
    end element from :paramref:`iterator`.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed value
    """
    text = _read_text_from_element(element, iterator)

    literal = aas_stringification.key_types_from_str(text)
    if literal is None:
        raise DeserializationException(
            f"Not a valid string representation of " f"a literal of KeyTypes: {text}"
        )

    return literal


def _read_data_type_def_xsd_from_element_text(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.DataTypeDefXSD:
    """
    Parse the text of :paramref:`element` as a literal of
    :py:class:`.types.DataTypeDefXSD`, and read the corresponding
    end element from :paramref:`iterator`.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed value
    """
    text = _read_text_from_element(element, iterator)

    literal = aas_stringification.data_type_def_xsd_from_str(text)
    if literal is None:
        raise DeserializationException(
            f"Not a valid string representation of "
            f"a literal of DataTypeDefXSD: {text}"
        )

    return literal


def _read_abstract_lang_string_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.AbstractLangString:
    """
    Read an instance of :py:class:`.types.AbstractLangString` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)
    read_as_sequence = _DISPATCH_FOR_ABSTRACT_LANG_STRING.get(tag_wo_ns, None)

    if read_as_sequence is None:
        raise DeserializationException(
            f"Expected the element tag to be a valid model type "
            f"of a concrete instance of 'AbstractLangString', "
            f"but got tag {tag_wo_ns!r}"
        )

    return read_as_sequence(element, iterator)


class _ReaderAndSetterForLangStringNameType:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`LangStringNameType`.

    The properties correspond to the constructor arguments of
    :py:class:`LangStringNameType`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.language: Optional[str] = None
        self.text: Optional[str] = None

    def read_and_set_language(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.LangStringNameType.language` and set it.
        """
        self.language = _read_str_from_element_text(element, iterator)

    def read_and_set_text(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.LangStringNameType.text` and set it.
        """
        self.text = _read_str_from_element_text(element, iterator)


def _read_lang_string_name_type_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.LangStringNameType:
    """
    Read an instance of :py:class:`.types.LangStringNameType`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForLangStringNameType()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_LANG_STRING_NAME_TYPE.get(
            tag_wo_ns, None
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.language is None:
        raise DeserializationException("The required property 'language' is missing")

    if reader_and_setter.text is None:
        raise DeserializationException("The required property 'text' is missing")

    return aas_types.LangStringNameType(
        reader_and_setter.language, reader_and_setter.text
    )


def _read_lang_string_name_type_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.LangStringNameType:
    """
    Read an instance of :py:class:`.types.LangStringNameType` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "langStringNameType":
        raise DeserializationException(
            f"Expected the element with the tag 'langStringNameType', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_lang_string_name_type_as_sequence(element, iterator)


class _ReaderAndSetterForLangStringTextType:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`LangStringTextType`.

    The properties correspond to the constructor arguments of
    :py:class:`LangStringTextType`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.language: Optional[str] = None
        self.text: Optional[str] = None

    def read_and_set_language(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.LangStringTextType.language` and set it.
        """
        self.language = _read_str_from_element_text(element, iterator)

    def read_and_set_text(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.LangStringTextType.text` and set it.
        """
        self.text = _read_str_from_element_text(element, iterator)


def _read_lang_string_text_type_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.LangStringTextType:
    """
    Read an instance of :py:class:`.types.LangStringTextType`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForLangStringTextType()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_LANG_STRING_TEXT_TYPE.get(
            tag_wo_ns, None
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.language is None:
        raise DeserializationException("The required property 'language' is missing")

    if reader_and_setter.text is None:
        raise DeserializationException("The required property 'text' is missing")

    return aas_types.LangStringTextType(
        reader_and_setter.language, reader_and_setter.text
    )


def _read_lang_string_text_type_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.LangStringTextType:
    """
    Read an instance of :py:class:`.types.LangStringTextType` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "langStringTextType":
        raise DeserializationException(
            f"Expected the element with the tag 'langStringTextType', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_lang_string_text_type_as_sequence(element, iterator)


class _ReaderAndSetterForEnvironment:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`Environment`.

    The properties correspond to the constructor arguments of
    :py:class:`Environment`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.asset_administration_shells: Optional[
            List[aas_types.AssetAdministrationShell]
        ] = None
        self.submodels: Optional[List[aas_types.Submodel]] = None
        self.concept_descriptions: Optional[List[aas_types.ConceptDescription]] = None

    def read_and_set_asset_administration_shells(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Environment.asset_administration_shells` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.AssetAdministrationShell] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_asset_administration_shell_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.asset_administration_shells = result

    def read_and_set_submodels(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Environment.submodels` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.Submodel] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_submodel_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.submodels = result

    def read_and_set_concept_descriptions(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.Environment.concept_descriptions` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.ConceptDescription] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_concept_description_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.concept_descriptions = result


def _read_environment_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Environment:
    """
    Read an instance of :py:class:`.types.Environment`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForEnvironment()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_ENVIRONMENT.get(
            tag_wo_ns, None
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    return aas_types.Environment(
        reader_and_setter.asset_administration_shells,
        reader_and_setter.submodels,
        reader_and_setter.concept_descriptions,
    )


def _read_environment_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Environment:
    """
    Read an instance of :py:class:`.types.Environment` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "environment":
        raise DeserializationException(
            f"Expected the element with the tag 'environment', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_environment_as_sequence(element, iterator)


def _read_data_specification_content_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.DataSpecificationContent:
    """
    Read an instance of :py:class:`.types.DataSpecificationContent` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)
    read_as_sequence = _DISPATCH_FOR_DATA_SPECIFICATION_CONTENT.get(tag_wo_ns, None)

    if read_as_sequence is None:
        raise DeserializationException(
            f"Expected the element tag to be a valid model type "
            f"of a concrete instance of 'DataSpecificationContent', "
            f"but got tag {tag_wo_ns!r}"
        )

    return read_as_sequence(element, iterator)


class _ReaderAndSetterForEmbeddedDataSpecification:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`EmbeddedDataSpecification`.

    The properties correspond to the constructor arguments of
    :py:class:`EmbeddedDataSpecification`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.data_specification: Optional[aas_types.Reference] = None
        self.data_specification_content: Optional[
            aas_types.DataSpecificationContent
        ] = None

    def read_and_set_data_specification(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.EmbeddedDataSpecification.data_specification` and set it.
        """
        self.data_specification = _read_reference_as_sequence(element, iterator)

    def read_and_set_data_specification_content(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.EmbeddedDataSpecification.data_specification_content` and set it.
        """
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected a discriminator start element corresponding "
                "to DataSpecificationContent, but got end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event != "start":
            raise DeserializationException(
                f"Expected a discriminator start element corresponding "
                f"to DataSpecificationContent, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            result = _read_data_specification_content_as_element(next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        _read_end_element(element, iterator)

        self.data_specification_content = result


def _read_embedded_data_specification_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.EmbeddedDataSpecification:
    """
    Read an instance of :py:class:`.types.EmbeddedDataSpecification`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForEmbeddedDataSpecification()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = (
            _READ_AND_SET_DISPATCH_FOR_EMBEDDED_DATA_SPECIFICATION.get(tag_wo_ns, None)
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.data_specification is None:
        raise DeserializationException(
            "The required property 'dataSpecification' is missing"
        )

    if reader_and_setter.data_specification_content is None:
        raise DeserializationException(
            "The required property 'dataSpecificationContent' is missing"
        )

    return aas_types.EmbeddedDataSpecification(
        reader_and_setter.data_specification,
        reader_and_setter.data_specification_content,
    )


def _read_embedded_data_specification_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.EmbeddedDataSpecification:
    """
    Read an instance of :py:class:`.types.EmbeddedDataSpecification` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "embeddedDataSpecification":
        raise DeserializationException(
            f"Expected the element with the tag 'embeddedDataSpecification', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_embedded_data_specification_as_sequence(element, iterator)


def _read_data_type_iec_61360_from_element_text(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.DataTypeIEC61360:
    """
    Parse the text of :paramref:`element` as a literal of
    :py:class:`.types.DataTypeIEC61360`, and read the corresponding
    end element from :paramref:`iterator`.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed value
    """
    text = _read_text_from_element(element, iterator)

    literal = aas_stringification.data_type_iec_61360_from_str(text)
    if literal is None:
        raise DeserializationException(
            f"Not a valid string representation of "
            f"a literal of DataTypeIEC61360: {text}"
        )

    return literal


class _ReaderAndSetterForLevelType:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`LevelType`.

    The properties correspond to the constructor arguments of
    :py:class:`LevelType`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.min: Optional[bool] = None
        self.nom: Optional[bool] = None
        self.typ: Optional[bool] = None
        self.max: Optional[bool] = None

    def read_and_set_min(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.LevelType.min` and set it.
        """
        self.min = _read_bool_from_element_text(element, iterator)

    def read_and_set_nom(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.LevelType.nom` and set it.
        """
        self.nom = _read_bool_from_element_text(element, iterator)

    def read_and_set_typ(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.LevelType.typ` and set it.
        """
        self.typ = _read_bool_from_element_text(element, iterator)

    def read_and_set_max(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.LevelType.max` and set it.
        """
        self.max = _read_bool_from_element_text(element, iterator)


def _read_level_type_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.LevelType:
    """
    Read an instance of :py:class:`.types.LevelType`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForLevelType()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_LEVEL_TYPE.get(tag_wo_ns, None)
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.min is None:
        raise DeserializationException("The required property 'min' is missing")

    if reader_and_setter.nom is None:
        raise DeserializationException("The required property 'nom' is missing")

    if reader_and_setter.typ is None:
        raise DeserializationException("The required property 'typ' is missing")

    if reader_and_setter.max is None:
        raise DeserializationException("The required property 'max' is missing")

    return aas_types.LevelType(
        reader_and_setter.min,
        reader_and_setter.nom,
        reader_and_setter.typ,
        reader_and_setter.max,
    )


def _read_level_type_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.LevelType:
    """
    Read an instance of :py:class:`.types.LevelType` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "levelType":
        raise DeserializationException(
            f"Expected the element with the tag 'levelType', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_level_type_as_sequence(element, iterator)


class _ReaderAndSetterForValueReferencePair:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`ValueReferencePair`.

    The properties correspond to the constructor arguments of
    :py:class:`ValueReferencePair`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.value: Optional[str] = None
        self.value_id: Optional[aas_types.Reference] = None

    def read_and_set_value(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ValueReferencePair.value` and set it.
        """
        self.value = _read_str_from_element_text(element, iterator)

    def read_and_set_value_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ValueReferencePair.value_id` and set it.
        """
        self.value_id = _read_reference_as_sequence(element, iterator)


def _read_value_reference_pair_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.ValueReferencePair:
    """
    Read an instance of :py:class:`.types.ValueReferencePair`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForValueReferencePair()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_VALUE_REFERENCE_PAIR.get(
            tag_wo_ns, None
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.value is None:
        raise DeserializationException("The required property 'value' is missing")

    if reader_and_setter.value_id is None:
        raise DeserializationException("The required property 'valueId' is missing")

    return aas_types.ValueReferencePair(
        reader_and_setter.value, reader_and_setter.value_id
    )


def _read_value_reference_pair_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.ValueReferencePair:
    """
    Read an instance of :py:class:`.types.ValueReferencePair` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "valueReferencePair":
        raise DeserializationException(
            f"Expected the element with the tag 'valueReferencePair', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_value_reference_pair_as_sequence(element, iterator)


class _ReaderAndSetterForValueList:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`ValueList`.

    The properties correspond to the constructor arguments of
    :py:class:`ValueList`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.value_reference_pairs: Optional[List[aas_types.ValueReferencePair]] = None

    def read_and_set_value_reference_pairs(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.ValueList.value_reference_pairs` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.ValueReferencePair] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_value_reference_pair_as_element(next_element, iterator)
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.value_reference_pairs = result


def _read_value_list_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.ValueList:
    """
    Read an instance of :py:class:`.types.ValueList`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForValueList()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = _READ_AND_SET_DISPATCH_FOR_VALUE_LIST.get(tag_wo_ns, None)
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.value_reference_pairs is None:
        raise DeserializationException(
            "The required property 'valueReferencePairs' is missing"
        )

    return aas_types.ValueList(reader_and_setter.value_reference_pairs)


def _read_value_list_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.ValueList:
    """
    Read an instance of :py:class:`.types.ValueList` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "valueList":
        raise DeserializationException(
            f"Expected the element with the tag 'valueList', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_value_list_as_sequence(element, iterator)


class _ReaderAndSetterForLangStringPreferredNameTypeIEC61360:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`LangStringPreferredNameTypeIEC61360`.

    The properties correspond to the constructor arguments of
    :py:class:`LangStringPreferredNameTypeIEC61360`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.language: Optional[str] = None
        self.text: Optional[str] = None

    def read_and_set_language(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.LangStringPreferredNameTypeIEC61360.language` and set it.
        """
        self.language = _read_str_from_element_text(element, iterator)

    def read_and_set_text(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.LangStringPreferredNameTypeIEC61360.text` and set it.
        """
        self.text = _read_str_from_element_text(element, iterator)


def _read_lang_string_preferred_name_type_iec_61360_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.LangStringPreferredNameTypeIEC61360:
    """
    Read an instance of :py:class:`.types.LangStringPreferredNameTypeIEC61360`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForLangStringPreferredNameTypeIEC61360()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = (
            _READ_AND_SET_DISPATCH_FOR_LANG_STRING_PREFERRED_NAME_TYPE_IEC_61360.get(
                tag_wo_ns, None
            )
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.language is None:
        raise DeserializationException("The required property 'language' is missing")

    if reader_and_setter.text is None:
        raise DeserializationException("The required property 'text' is missing")

    return aas_types.LangStringPreferredNameTypeIEC61360(
        reader_and_setter.language, reader_and_setter.text
    )


def _read_lang_string_preferred_name_type_iec_61360_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.LangStringPreferredNameTypeIEC61360:
    """
    Read an instance of :py:class:`.types.LangStringPreferredNameTypeIEC61360` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "langStringPreferredNameTypeIec61360":
        raise DeserializationException(
            f"Expected the element with the tag 'langStringPreferredNameTypeIec61360', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_lang_string_preferred_name_type_iec_61360_as_sequence(
        element, iterator
    )


class _ReaderAndSetterForLangStringShortNameTypeIEC61360:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`LangStringShortNameTypeIEC61360`.

    The properties correspond to the constructor arguments of
    :py:class:`LangStringShortNameTypeIEC61360`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.language: Optional[str] = None
        self.text: Optional[str] = None

    def read_and_set_language(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.LangStringShortNameTypeIEC61360.language` and set it.
        """
        self.language = _read_str_from_element_text(element, iterator)

    def read_and_set_text(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.LangStringShortNameTypeIEC61360.text` and set it.
        """
        self.text = _read_str_from_element_text(element, iterator)


def _read_lang_string_short_name_type_iec_61360_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.LangStringShortNameTypeIEC61360:
    """
    Read an instance of :py:class:`.types.LangStringShortNameTypeIEC61360`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForLangStringShortNameTypeIEC61360()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = (
            _READ_AND_SET_DISPATCH_FOR_LANG_STRING_SHORT_NAME_TYPE_IEC_61360.get(
                tag_wo_ns, None
            )
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.language is None:
        raise DeserializationException("The required property 'language' is missing")

    if reader_and_setter.text is None:
        raise DeserializationException("The required property 'text' is missing")

    return aas_types.LangStringShortNameTypeIEC61360(
        reader_and_setter.language, reader_and_setter.text
    )


def _read_lang_string_short_name_type_iec_61360_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.LangStringShortNameTypeIEC61360:
    """
    Read an instance of :py:class:`.types.LangStringShortNameTypeIEC61360` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "langStringShortNameTypeIec61360":
        raise DeserializationException(
            f"Expected the element with the tag 'langStringShortNameTypeIec61360', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_lang_string_short_name_type_iec_61360_as_sequence(element, iterator)


class _ReaderAndSetterForLangStringDefinitionTypeIEC61360:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`LangStringDefinitionTypeIEC61360`.

    The properties correspond to the constructor arguments of
    :py:class:`LangStringDefinitionTypeIEC61360`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.language: Optional[str] = None
        self.text: Optional[str] = None

    def read_and_set_language(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.LangStringDefinitionTypeIEC61360.language` and set it.
        """
        self.language = _read_str_from_element_text(element, iterator)

    def read_and_set_text(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.LangStringDefinitionTypeIEC61360.text` and set it.
        """
        self.text = _read_str_from_element_text(element, iterator)


def _read_lang_string_definition_type_iec_61360_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.LangStringDefinitionTypeIEC61360:
    """
    Read an instance of :py:class:`.types.LangStringDefinitionTypeIEC61360`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForLangStringDefinitionTypeIEC61360()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = (
            _READ_AND_SET_DISPATCH_FOR_LANG_STRING_DEFINITION_TYPE_IEC_61360.get(
                tag_wo_ns, None
            )
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.language is None:
        raise DeserializationException("The required property 'language' is missing")

    if reader_and_setter.text is None:
        raise DeserializationException("The required property 'text' is missing")

    return aas_types.LangStringDefinitionTypeIEC61360(
        reader_and_setter.language, reader_and_setter.text
    )


def _read_lang_string_definition_type_iec_61360_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.LangStringDefinitionTypeIEC61360:
    """
    Read an instance of :py:class:`.types.LangStringDefinitionTypeIEC61360` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "langStringDefinitionTypeIec61360":
        raise DeserializationException(
            f"Expected the element with the tag 'langStringDefinitionTypeIec61360', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_lang_string_definition_type_iec_61360_as_sequence(element, iterator)


class _ReaderAndSetterForDataSpecificationIEC61360:
    """
    Provide a buffer for reading and setting the properties for the class
    :py:class:`DataSpecificationIEC61360`.

    The properties correspond to the constructor arguments of
    :py:class:`DataSpecificationIEC61360`. We use this buffer to facilitate dispatching when
    parsing the properties in a streaming fashion.
    """

    def __init__(self) -> None:
        """Initialize with all the properties unset."""
        self.preferred_name: Optional[
            List[aas_types.LangStringPreferredNameTypeIEC61360]
        ] = None
        self.short_name: Optional[
            List[aas_types.LangStringShortNameTypeIEC61360]
        ] = None
        self.unit: Optional[str] = None
        self.unit_id: Optional[aas_types.Reference] = None
        self.source_of_definition: Optional[str] = None
        self.symbol: Optional[str] = None
        self.data_type: Optional[aas_types.DataTypeIEC61360] = None
        self.definition: Optional[
            List[aas_types.LangStringDefinitionTypeIEC61360]
        ] = None
        self.value_format: Optional[str] = None
        self.value_list: Optional[aas_types.ValueList] = None
        self.value: Optional[str] = None
        self.level_type: Optional[aas_types.LevelType] = None

    def read_and_set_preferred_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.DataSpecificationIEC61360.preferred_name` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringPreferredNameTypeIEC61360] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_preferred_name_type_iec_61360_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.preferred_name = result

    def read_and_set_short_name(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.DataSpecificationIEC61360.short_name` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringShortNameTypeIEC61360] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_short_name_type_iec_61360_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.short_name = result

    def read_and_set_unit(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.DataSpecificationIEC61360.unit` and set it.
        """
        self.unit = _read_str_from_element_text(element, iterator)

    def read_and_set_unit_id(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.DataSpecificationIEC61360.unit_id` and set it.
        """
        self.unit_id = _read_reference_as_sequence(element, iterator)

    def read_and_set_source_of_definition(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.DataSpecificationIEC61360.source_of_definition` and set it.
        """
        self.source_of_definition = _read_str_from_element_text(element, iterator)

    def read_and_set_symbol(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.DataSpecificationIEC61360.symbol` and set it.
        """
        self.symbol = _read_str_from_element_text(element, iterator)

    def read_and_set_data_type(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.DataSpecificationIEC61360.data_type` and set it.
        """
        self.data_type = _read_data_type_iec_61360_from_element_text(element, iterator)

    def read_and_set_definition(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.DataSpecificationIEC61360.definition` and set it.
        """
        if element.text is not None and len(element.text.strip()) != 0:
            raise DeserializationException(
                f"Expected only item elements and whitespace text, "
                f"but got text: {element.text!r}"
            )

        result: List[aas_types.LangStringDefinitionTypeIEC61360] = []

        item_i = 0

        while True:
            next_event_element = next(iterator, None)
            if next_event_element is None:
                raise DeserializationException(
                    "Expected one or more items from a list or the end element, "
                    "but got end-of-input"
                )

            next_event, next_element = next_event_element
            if next_event == "end" and next_element.tag == element.tag:
                # We reached the end of the list.
                break

            if next_event != "start":
                raise DeserializationException(
                    "Expected a start element corresponding to an item, "
                    f"but got event {next_event!r} and element {next_element.tag!r}"
                )

            try:
                item = _read_lang_string_definition_type_iec_61360_as_element(
                    next_element, iterator
                )
            except DeserializationException as exception:
                exception.path._prepend(IndexSegment(next_element, item_i))
                raise

            result.append(item)
            item_i += 1

        self.definition = result

    def read_and_set_value_format(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.DataSpecificationIEC61360.value_format` and set it.
        """
        self.value_format = _read_str_from_element_text(element, iterator)

    def read_and_set_value_list(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.DataSpecificationIEC61360.value_list` and set it.
        """
        self.value_list = _read_value_list_as_sequence(element, iterator)

    def read_and_set_value(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.DataSpecificationIEC61360.value` and set it.
        """
        self.value = _read_str_from_element_text(element, iterator)

    def read_and_set_level_type(
        self, element: Element, iterator: Iterator[Tuple[str, Element]]
    ) -> None:
        """
        Read :paramref:`element` as the property
        :py:attr:`.types.DataSpecificationIEC61360.level_type` and set it.
        """
        self.level_type = _read_level_type_as_sequence(element, iterator)


def _read_data_specification_iec_61360_as_sequence(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.DataSpecificationIEC61360:
    """
    Read an instance of :py:class:`.types.DataSpecificationIEC61360`
    as a sequence of XML-encoded properties.

    The end element corresponding to the :paramref:`element` will be
    read as well.

    :param element: start element, parent of the sequence
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    if element.text is not None and len(element.text.strip()) != 0:
        raise DeserializationException(
            f"Expected only XML elements representing the properties and whitespace text, "
            f"but got text: {element.text!r}"
        )

    _raise_if_has_tail_or_attrib(element)

    reader_and_setter = _ReaderAndSetterForDataSpecificationIEC61360()

    while True:
        next_event_element = next(iterator, None)
        if next_event_element is None:
            raise DeserializationException(
                "Expected one or more XML-encoded properties or the end element, "
                "but got the end-of-input"
            )

        next_event, next_element = next_event_element
        if next_event == "end" and next_element.tag == element.tag:
            # We reached the end element enclosing the sequence.
            break

        if next_event != "start":
            raise DeserializationException(
                "Expected a start element corresponding to a property, "
                f"but got event {next_event!r} and element {next_element.tag!r}"
            )

        try:
            tag_wo_ns = _parse_element_tag(next_element)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

        read_and_set_method = (
            _READ_AND_SET_DISPATCH_FOR_DATA_SPECIFICATION_IEC_61360.get(tag_wo_ns, None)
        )
        if read_and_set_method is None:
            an_exception = DeserializationException(
                f"Expected an element representing a property, "
                f"but got an element with unexpected tag: {tag_wo_ns!r}"
            )
            an_exception.path._prepend(ElementSegment(next_element))
            raise an_exception

        try:
            read_and_set_method(reader_and_setter, next_element, iterator)
        except DeserializationException as exception:
            exception.path._prepend(ElementSegment(next_element))
            raise

    if reader_and_setter.preferred_name is None:
        raise DeserializationException(
            "The required property 'preferredName' is missing"
        )

    return aas_types.DataSpecificationIEC61360(
        reader_and_setter.preferred_name,
        reader_and_setter.short_name,
        reader_and_setter.unit,
        reader_and_setter.unit_id,
        reader_and_setter.source_of_definition,
        reader_and_setter.symbol,
        reader_and_setter.data_type,
        reader_and_setter.definition,
        reader_and_setter.value_format,
        reader_and_setter.value_list,
        reader_and_setter.value,
        reader_and_setter.level_type,
    )


def _read_data_specification_iec_61360_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.DataSpecificationIEC61360:
    """
    Read an instance of :py:class:`.types.DataSpecificationIEC61360` from
    :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)

    if tag_wo_ns != "dataSpecificationIec61360":
        raise DeserializationException(
            f"Expected the element with the tag 'dataSpecificationIec61360', "
            f"but got tag: {tag_wo_ns}"
        )

    return _read_data_specification_iec_61360_as_sequence(element, iterator)


def _read_as_element(
    element: Element, iterator: Iterator[Tuple[str, Element]]
) -> aas_types.Class:
    """
    Read an instance from :paramref:`iterator`, including the end element.

    :param element: start element
    :param iterator:
        Input stream of ``(event, element)`` coming from
        :py:func:`xml.etree.ElementTree.iterparse` with the argument
        ``events=["start", "end"]``
    :raise: :py:class:`DeserializationException` if unexpected input
    :return: parsed instance
    """
    tag_wo_ns = _parse_element_tag(element)
    read_as_sequence = _GENERAL_DISPATCH.get(tag_wo_ns, None)

    if read_as_sequence is None:
        raise DeserializationException(
            f"Expected the element tag to be a valid model type "
            f"of a concrete instance, "
            f"but got tag {tag_wo_ns!r}"
        )

    return read_as_sequence(element, iterator)


#: Dispatch XML class names to read-as-sequence functions
#: corresponding to concrete descendants of HasSemantics
_DISPATCH_FOR_HAS_SEMANTICS: Mapping[
    str, Callable[[Element, Iterator[Tuple[str, Element]]], aas_types.HasSemantics]
] = {
    "relationshipElement": _read_relationship_element_as_sequence,
    "annotatedRelationshipElement": _read_annotated_relationship_element_as_sequence,
    "basicEventElement": _read_basic_event_element_as_sequence,
    "blob": _read_blob_as_sequence,
    "capability": _read_capability_as_sequence,
    "entity": _read_entity_as_sequence,
    "extension": _read_extension_as_sequence,
    "file": _read_file_as_sequence,
    "multiLanguageProperty": _read_multi_language_property_as_sequence,
    "operation": _read_operation_as_sequence,
    "property": _read_property_as_sequence,
    "qualifier": _read_qualifier_as_sequence,
    "range": _read_range_as_sequence,
    "referenceElement": _read_reference_element_as_sequence,
    "specificAssetId": _read_specific_asset_id_as_sequence,
    "submodel": _read_submodel_as_sequence,
    "submodelElementCollection": _read_submodel_element_collection_as_sequence,
    "submodelElementList": _read_submodel_element_list_as_sequence,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForExtension`
_READ_AND_SET_DISPATCH_FOR_EXTENSION: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForExtension, Element, Iterator[Tuple[str, Element]]], None
    ],
] = {
    "semanticId": _ReaderAndSetterForExtension.read_and_set_semantic_id,
    "supplementalSemanticIds": _ReaderAndSetterForExtension.read_and_set_supplemental_semantic_ids,
    "name": _ReaderAndSetterForExtension.read_and_set_name,
    "valueType": _ReaderAndSetterForExtension.read_and_set_value_type,
    "value": _ReaderAndSetterForExtension.read_and_set_value,
    "refersTo": _ReaderAndSetterForExtension.read_and_set_refers_to,
}


#: Dispatch XML class names to read-as-sequence functions
#: corresponding to concrete descendants of HasExtensions
_DISPATCH_FOR_HAS_EXTENSIONS: Mapping[
    str, Callable[[Element, Iterator[Tuple[str, Element]]], aas_types.HasExtensions]
] = {
    "relationshipElement": _read_relationship_element_as_sequence,
    "annotatedRelationshipElement": _read_annotated_relationship_element_as_sequence,
    "assetAdministrationShell": _read_asset_administration_shell_as_sequence,
    "basicEventElement": _read_basic_event_element_as_sequence,
    "blob": _read_blob_as_sequence,
    "capability": _read_capability_as_sequence,
    "conceptDescription": _read_concept_description_as_sequence,
    "entity": _read_entity_as_sequence,
    "file": _read_file_as_sequence,
    "multiLanguageProperty": _read_multi_language_property_as_sequence,
    "operation": _read_operation_as_sequence,
    "property": _read_property_as_sequence,
    "range": _read_range_as_sequence,
    "referenceElement": _read_reference_element_as_sequence,
    "submodel": _read_submodel_as_sequence,
    "submodelElementCollection": _read_submodel_element_collection_as_sequence,
    "submodelElementList": _read_submodel_element_list_as_sequence,
}


#: Dispatch XML class names to read-as-sequence functions
#: corresponding to concrete descendants of Referable
_DISPATCH_FOR_REFERABLE: Mapping[
    str, Callable[[Element, Iterator[Tuple[str, Element]]], aas_types.Referable]
] = {
    "relationshipElement": _read_relationship_element_as_sequence,
    "annotatedRelationshipElement": _read_annotated_relationship_element_as_sequence,
    "assetAdministrationShell": _read_asset_administration_shell_as_sequence,
    "basicEventElement": _read_basic_event_element_as_sequence,
    "blob": _read_blob_as_sequence,
    "capability": _read_capability_as_sequence,
    "conceptDescription": _read_concept_description_as_sequence,
    "entity": _read_entity_as_sequence,
    "file": _read_file_as_sequence,
    "multiLanguageProperty": _read_multi_language_property_as_sequence,
    "operation": _read_operation_as_sequence,
    "property": _read_property_as_sequence,
    "range": _read_range_as_sequence,
    "referenceElement": _read_reference_element_as_sequence,
    "submodel": _read_submodel_as_sequence,
    "submodelElementCollection": _read_submodel_element_collection_as_sequence,
    "submodelElementList": _read_submodel_element_list_as_sequence,
}


#: Dispatch XML class names to read-as-sequence functions
#: corresponding to concrete descendants of Identifiable
_DISPATCH_FOR_IDENTIFIABLE: Mapping[
    str, Callable[[Element, Iterator[Tuple[str, Element]]], aas_types.Identifiable]
] = {
    "assetAdministrationShell": _read_asset_administration_shell_as_sequence,
    "conceptDescription": _read_concept_description_as_sequence,
    "submodel": _read_submodel_as_sequence,
}


#: Dispatch XML class names to read-as-sequence functions
#: corresponding to concrete descendants of HasKind
_DISPATCH_FOR_HAS_KIND: Mapping[
    str, Callable[[Element, Iterator[Tuple[str, Element]]], aas_types.HasKind]
] = {
    "submodel": _read_submodel_as_sequence,
}


#: Dispatch XML class names to read-as-sequence functions
#: corresponding to concrete descendants of HasDataSpecification
_DISPATCH_FOR_HAS_DATA_SPECIFICATION: Mapping[
    str,
    Callable[[Element, Iterator[Tuple[str, Element]]], aas_types.HasDataSpecification],
] = {
    "administrativeInformation": _read_administrative_information_as_sequence,
    "relationshipElement": _read_relationship_element_as_sequence,
    "annotatedRelationshipElement": _read_annotated_relationship_element_as_sequence,
    "assetAdministrationShell": _read_asset_administration_shell_as_sequence,
    "basicEventElement": _read_basic_event_element_as_sequence,
    "blob": _read_blob_as_sequence,
    "capability": _read_capability_as_sequence,
    "conceptDescription": _read_concept_description_as_sequence,
    "entity": _read_entity_as_sequence,
    "file": _read_file_as_sequence,
    "multiLanguageProperty": _read_multi_language_property_as_sequence,
    "operation": _read_operation_as_sequence,
    "property": _read_property_as_sequence,
    "range": _read_range_as_sequence,
    "referenceElement": _read_reference_element_as_sequence,
    "submodel": _read_submodel_as_sequence,
    "submodelElementCollection": _read_submodel_element_collection_as_sequence,
    "submodelElementList": _read_submodel_element_list_as_sequence,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForAdministrativeInformation`
_READ_AND_SET_DISPATCH_FOR_ADMINISTRATIVE_INFORMATION: Mapping[
    str,
    Callable[
        [
            _ReaderAndSetterForAdministrativeInformation,
            Element,
            Iterator[Tuple[str, Element]],
        ],
        None,
    ],
] = {
    "embeddedDataSpecifications": _ReaderAndSetterForAdministrativeInformation.read_and_set_embedded_data_specifications,
    "version": _ReaderAndSetterForAdministrativeInformation.read_and_set_version,
    "revision": _ReaderAndSetterForAdministrativeInformation.read_and_set_revision,
    "creator": _ReaderAndSetterForAdministrativeInformation.read_and_set_creator,
    "templateId": _ReaderAndSetterForAdministrativeInformation.read_and_set_template_id,
}


#: Dispatch XML class names to read-as-sequence functions
#: corresponding to concrete descendants of Qualifiable
_DISPATCH_FOR_QUALIFIABLE: Mapping[
    str, Callable[[Element, Iterator[Tuple[str, Element]]], aas_types.Qualifiable]
] = {
    "relationshipElement": _read_relationship_element_as_sequence,
    "annotatedRelationshipElement": _read_annotated_relationship_element_as_sequence,
    "basicEventElement": _read_basic_event_element_as_sequence,
    "blob": _read_blob_as_sequence,
    "capability": _read_capability_as_sequence,
    "entity": _read_entity_as_sequence,
    "file": _read_file_as_sequence,
    "multiLanguageProperty": _read_multi_language_property_as_sequence,
    "operation": _read_operation_as_sequence,
    "property": _read_property_as_sequence,
    "range": _read_range_as_sequence,
    "referenceElement": _read_reference_element_as_sequence,
    "submodel": _read_submodel_as_sequence,
    "submodelElementCollection": _read_submodel_element_collection_as_sequence,
    "submodelElementList": _read_submodel_element_list_as_sequence,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForQualifier`
_READ_AND_SET_DISPATCH_FOR_QUALIFIER: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForQualifier, Element, Iterator[Tuple[str, Element]]], None
    ],
] = {
    "semanticId": _ReaderAndSetterForQualifier.read_and_set_semantic_id,
    "supplementalSemanticIds": _ReaderAndSetterForQualifier.read_and_set_supplemental_semantic_ids,
    "kind": _ReaderAndSetterForQualifier.read_and_set_kind,
    "type": _ReaderAndSetterForQualifier.read_and_set_type,
    "valueType": _ReaderAndSetterForQualifier.read_and_set_value_type,
    "value": _ReaderAndSetterForQualifier.read_and_set_value,
    "valueId": _ReaderAndSetterForQualifier.read_and_set_value_id,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForAssetAdministrationShell`
_READ_AND_SET_DISPATCH_FOR_ASSET_ADMINISTRATION_SHELL: Mapping[
    str,
    Callable[
        [
            _ReaderAndSetterForAssetAdministrationShell,
            Element,
            Iterator[Tuple[str, Element]],
        ],
        None,
    ],
] = {
    "extensions": _ReaderAndSetterForAssetAdministrationShell.read_and_set_extensions,
    "category": _ReaderAndSetterForAssetAdministrationShell.read_and_set_category,
    "idShort": _ReaderAndSetterForAssetAdministrationShell.read_and_set_id_short,
    "displayName": _ReaderAndSetterForAssetAdministrationShell.read_and_set_display_name,
    "description": _ReaderAndSetterForAssetAdministrationShell.read_and_set_description,
    "administration": _ReaderAndSetterForAssetAdministrationShell.read_and_set_administration,
    "id": _ReaderAndSetterForAssetAdministrationShell.read_and_set_id,
    "embeddedDataSpecifications": _ReaderAndSetterForAssetAdministrationShell.read_and_set_embedded_data_specifications,
    "derivedFrom": _ReaderAndSetterForAssetAdministrationShell.read_and_set_derived_from,
    "assetInformation": _ReaderAndSetterForAssetAdministrationShell.read_and_set_asset_information,
    "submodels": _ReaderAndSetterForAssetAdministrationShell.read_and_set_submodels,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForAssetInformation`
_READ_AND_SET_DISPATCH_FOR_ASSET_INFORMATION: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForAssetInformation, Element, Iterator[Tuple[str, Element]]],
        None,
    ],
] = {
    "assetKind": _ReaderAndSetterForAssetInformation.read_and_set_asset_kind,
    "globalAssetId": _ReaderAndSetterForAssetInformation.read_and_set_global_asset_id,
    "specificAssetIds": _ReaderAndSetterForAssetInformation.read_and_set_specific_asset_ids,
    "assetType": _ReaderAndSetterForAssetInformation.read_and_set_asset_type,
    "defaultThumbnail": _ReaderAndSetterForAssetInformation.read_and_set_default_thumbnail,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForResource`
_READ_AND_SET_DISPATCH_FOR_RESOURCE: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForResource, Element, Iterator[Tuple[str, Element]]], None
    ],
] = {
    "path": _ReaderAndSetterForResource.read_and_set_path,
    "contentType": _ReaderAndSetterForResource.read_and_set_content_type,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForSpecificAssetID`
_READ_AND_SET_DISPATCH_FOR_SPECIFIC_ASSET_ID: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForSpecificAssetID, Element, Iterator[Tuple[str, Element]]],
        None,
    ],
] = {
    "semanticId": _ReaderAndSetterForSpecificAssetID.read_and_set_semantic_id,
    "supplementalSemanticIds": _ReaderAndSetterForSpecificAssetID.read_and_set_supplemental_semantic_ids,
    "name": _ReaderAndSetterForSpecificAssetID.read_and_set_name,
    "value": _ReaderAndSetterForSpecificAssetID.read_and_set_value,
    "externalSubjectId": _ReaderAndSetterForSpecificAssetID.read_and_set_external_subject_id,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForSubmodel`
_READ_AND_SET_DISPATCH_FOR_SUBMODEL: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForSubmodel, Element, Iterator[Tuple[str, Element]]], None
    ],
] = {
    "extensions": _ReaderAndSetterForSubmodel.read_and_set_extensions,
    "category": _ReaderAndSetterForSubmodel.read_and_set_category,
    "idShort": _ReaderAndSetterForSubmodel.read_and_set_id_short,
    "displayName": _ReaderAndSetterForSubmodel.read_and_set_display_name,
    "description": _ReaderAndSetterForSubmodel.read_and_set_description,
    "administration": _ReaderAndSetterForSubmodel.read_and_set_administration,
    "id": _ReaderAndSetterForSubmodel.read_and_set_id,
    "kind": _ReaderAndSetterForSubmodel.read_and_set_kind,
    "semanticId": _ReaderAndSetterForSubmodel.read_and_set_semantic_id,
    "supplementalSemanticIds": _ReaderAndSetterForSubmodel.read_and_set_supplemental_semantic_ids,
    "qualifiers": _ReaderAndSetterForSubmodel.read_and_set_qualifiers,
    "embeddedDataSpecifications": _ReaderAndSetterForSubmodel.read_and_set_embedded_data_specifications,
    "submodelElements": _ReaderAndSetterForSubmodel.read_and_set_submodel_elements,
}


#: Dispatch XML class names to read-as-sequence functions
#: corresponding to concrete descendants of SubmodelElement
_DISPATCH_FOR_SUBMODEL_ELEMENT: Mapping[
    str, Callable[[Element, Iterator[Tuple[str, Element]]], aas_types.SubmodelElement]
] = {
    "relationshipElement": _read_relationship_element_as_sequence,
    "annotatedRelationshipElement": _read_annotated_relationship_element_as_sequence,
    "basicEventElement": _read_basic_event_element_as_sequence,
    "blob": _read_blob_as_sequence,
    "capability": _read_capability_as_sequence,
    "entity": _read_entity_as_sequence,
    "file": _read_file_as_sequence,
    "multiLanguageProperty": _read_multi_language_property_as_sequence,
    "operation": _read_operation_as_sequence,
    "property": _read_property_as_sequence,
    "range": _read_range_as_sequence,
    "referenceElement": _read_reference_element_as_sequence,
    "submodelElementCollection": _read_submodel_element_collection_as_sequence,
    "submodelElementList": _read_submodel_element_list_as_sequence,
}


#: Dispatch XML class names to read-as-sequence functions
#: corresponding to RelationshipElement and its concrete descendants
_DISPATCH_FOR_RELATIONSHIP_ELEMENT: Mapping[
    str,
    Callable[[Element, Iterator[Tuple[str, Element]]], aas_types.RelationshipElement],
] = {
    "relationshipElement": _read_relationship_element_as_sequence,
    "annotatedRelationshipElement": _read_annotated_relationship_element_as_sequence,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForRelationshipElement`
_READ_AND_SET_DISPATCH_FOR_RELATIONSHIP_ELEMENT: Mapping[
    str,
    Callable[
        [
            _ReaderAndSetterForRelationshipElement,
            Element,
            Iterator[Tuple[str, Element]],
        ],
        None,
    ],
] = {
    "extensions": _ReaderAndSetterForRelationshipElement.read_and_set_extensions,
    "category": _ReaderAndSetterForRelationshipElement.read_and_set_category,
    "idShort": _ReaderAndSetterForRelationshipElement.read_and_set_id_short,
    "displayName": _ReaderAndSetterForRelationshipElement.read_and_set_display_name,
    "description": _ReaderAndSetterForRelationshipElement.read_and_set_description,
    "semanticId": _ReaderAndSetterForRelationshipElement.read_and_set_semantic_id,
    "supplementalSemanticIds": _ReaderAndSetterForRelationshipElement.read_and_set_supplemental_semantic_ids,
    "qualifiers": _ReaderAndSetterForRelationshipElement.read_and_set_qualifiers,
    "embeddedDataSpecifications": _ReaderAndSetterForRelationshipElement.read_and_set_embedded_data_specifications,
    "first": _ReaderAndSetterForRelationshipElement.read_and_set_first,
    "second": _ReaderAndSetterForRelationshipElement.read_and_set_second,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForSubmodelElementList`
_READ_AND_SET_DISPATCH_FOR_SUBMODEL_ELEMENT_LIST: Mapping[
    str,
    Callable[
        [
            _ReaderAndSetterForSubmodelElementList,
            Element,
            Iterator[Tuple[str, Element]],
        ],
        None,
    ],
] = {
    "extensions": _ReaderAndSetterForSubmodelElementList.read_and_set_extensions,
    "category": _ReaderAndSetterForSubmodelElementList.read_and_set_category,
    "idShort": _ReaderAndSetterForSubmodelElementList.read_and_set_id_short,
    "displayName": _ReaderAndSetterForSubmodelElementList.read_and_set_display_name,
    "description": _ReaderAndSetterForSubmodelElementList.read_and_set_description,
    "semanticId": _ReaderAndSetterForSubmodelElementList.read_and_set_semantic_id,
    "supplementalSemanticIds": _ReaderAndSetterForSubmodelElementList.read_and_set_supplemental_semantic_ids,
    "qualifiers": _ReaderAndSetterForSubmodelElementList.read_and_set_qualifiers,
    "embeddedDataSpecifications": _ReaderAndSetterForSubmodelElementList.read_and_set_embedded_data_specifications,
    "orderRelevant": _ReaderAndSetterForSubmodelElementList.read_and_set_order_relevant,
    "semanticIdListElement": _ReaderAndSetterForSubmodelElementList.read_and_set_semantic_id_list_element,
    "typeValueListElement": _ReaderAndSetterForSubmodelElementList.read_and_set_type_value_list_element,
    "valueTypeListElement": _ReaderAndSetterForSubmodelElementList.read_and_set_value_type_list_element,
    "value": _ReaderAndSetterForSubmodelElementList.read_and_set_value,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForSubmodelElementCollection`
_READ_AND_SET_DISPATCH_FOR_SUBMODEL_ELEMENT_COLLECTION: Mapping[
    str,
    Callable[
        [
            _ReaderAndSetterForSubmodelElementCollection,
            Element,
            Iterator[Tuple[str, Element]],
        ],
        None,
    ],
] = {
    "extensions": _ReaderAndSetterForSubmodelElementCollection.read_and_set_extensions,
    "category": _ReaderAndSetterForSubmodelElementCollection.read_and_set_category,
    "idShort": _ReaderAndSetterForSubmodelElementCollection.read_and_set_id_short,
    "displayName": _ReaderAndSetterForSubmodelElementCollection.read_and_set_display_name,
    "description": _ReaderAndSetterForSubmodelElementCollection.read_and_set_description,
    "semanticId": _ReaderAndSetterForSubmodelElementCollection.read_and_set_semantic_id,
    "supplementalSemanticIds": _ReaderAndSetterForSubmodelElementCollection.read_and_set_supplemental_semantic_ids,
    "qualifiers": _ReaderAndSetterForSubmodelElementCollection.read_and_set_qualifiers,
    "embeddedDataSpecifications": _ReaderAndSetterForSubmodelElementCollection.read_and_set_embedded_data_specifications,
    "value": _ReaderAndSetterForSubmodelElementCollection.read_and_set_value,
}


#: Dispatch XML class names to read-as-sequence functions
#: corresponding to concrete descendants of DataElement
_DISPATCH_FOR_DATA_ELEMENT: Mapping[
    str, Callable[[Element, Iterator[Tuple[str, Element]]], aas_types.DataElement]
] = {
    "blob": _read_blob_as_sequence,
    "file": _read_file_as_sequence,
    "multiLanguageProperty": _read_multi_language_property_as_sequence,
    "property": _read_property_as_sequence,
    "range": _read_range_as_sequence,
    "referenceElement": _read_reference_element_as_sequence,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForProperty`
_READ_AND_SET_DISPATCH_FOR_PROPERTY: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForProperty, Element, Iterator[Tuple[str, Element]]], None
    ],
] = {
    "extensions": _ReaderAndSetterForProperty.read_and_set_extensions,
    "category": _ReaderAndSetterForProperty.read_and_set_category,
    "idShort": _ReaderAndSetterForProperty.read_and_set_id_short,
    "displayName": _ReaderAndSetterForProperty.read_and_set_display_name,
    "description": _ReaderAndSetterForProperty.read_and_set_description,
    "semanticId": _ReaderAndSetterForProperty.read_and_set_semantic_id,
    "supplementalSemanticIds": _ReaderAndSetterForProperty.read_and_set_supplemental_semantic_ids,
    "qualifiers": _ReaderAndSetterForProperty.read_and_set_qualifiers,
    "embeddedDataSpecifications": _ReaderAndSetterForProperty.read_and_set_embedded_data_specifications,
    "valueType": _ReaderAndSetterForProperty.read_and_set_value_type,
    "value": _ReaderAndSetterForProperty.read_and_set_value,
    "valueId": _ReaderAndSetterForProperty.read_and_set_value_id,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForMultiLanguageProperty`
_READ_AND_SET_DISPATCH_FOR_MULTI_LANGUAGE_PROPERTY: Mapping[
    str,
    Callable[
        [
            _ReaderAndSetterForMultiLanguageProperty,
            Element,
            Iterator[Tuple[str, Element]],
        ],
        None,
    ],
] = {
    "extensions": _ReaderAndSetterForMultiLanguageProperty.read_and_set_extensions,
    "category": _ReaderAndSetterForMultiLanguageProperty.read_and_set_category,
    "idShort": _ReaderAndSetterForMultiLanguageProperty.read_and_set_id_short,
    "displayName": _ReaderAndSetterForMultiLanguageProperty.read_and_set_display_name,
    "description": _ReaderAndSetterForMultiLanguageProperty.read_and_set_description,
    "semanticId": _ReaderAndSetterForMultiLanguageProperty.read_and_set_semantic_id,
    "supplementalSemanticIds": _ReaderAndSetterForMultiLanguageProperty.read_and_set_supplemental_semantic_ids,
    "qualifiers": _ReaderAndSetterForMultiLanguageProperty.read_and_set_qualifiers,
    "embeddedDataSpecifications": _ReaderAndSetterForMultiLanguageProperty.read_and_set_embedded_data_specifications,
    "value": _ReaderAndSetterForMultiLanguageProperty.read_and_set_value,
    "valueId": _ReaderAndSetterForMultiLanguageProperty.read_and_set_value_id,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForRange`
_READ_AND_SET_DISPATCH_FOR_RANGE: Mapping[
    str,
    Callable[[_ReaderAndSetterForRange, Element, Iterator[Tuple[str, Element]]], None],
] = {
    "extensions": _ReaderAndSetterForRange.read_and_set_extensions,
    "category": _ReaderAndSetterForRange.read_and_set_category,
    "idShort": _ReaderAndSetterForRange.read_and_set_id_short,
    "displayName": _ReaderAndSetterForRange.read_and_set_display_name,
    "description": _ReaderAndSetterForRange.read_and_set_description,
    "semanticId": _ReaderAndSetterForRange.read_and_set_semantic_id,
    "supplementalSemanticIds": _ReaderAndSetterForRange.read_and_set_supplemental_semantic_ids,
    "qualifiers": _ReaderAndSetterForRange.read_and_set_qualifiers,
    "embeddedDataSpecifications": _ReaderAndSetterForRange.read_and_set_embedded_data_specifications,
    "valueType": _ReaderAndSetterForRange.read_and_set_value_type,
    "min": _ReaderAndSetterForRange.read_and_set_min,
    "max": _ReaderAndSetterForRange.read_and_set_max,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForReferenceElement`
_READ_AND_SET_DISPATCH_FOR_REFERENCE_ELEMENT: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForReferenceElement, Element, Iterator[Tuple[str, Element]]],
        None,
    ],
] = {
    "extensions": _ReaderAndSetterForReferenceElement.read_and_set_extensions,
    "category": _ReaderAndSetterForReferenceElement.read_and_set_category,
    "idShort": _ReaderAndSetterForReferenceElement.read_and_set_id_short,
    "displayName": _ReaderAndSetterForReferenceElement.read_and_set_display_name,
    "description": _ReaderAndSetterForReferenceElement.read_and_set_description,
    "semanticId": _ReaderAndSetterForReferenceElement.read_and_set_semantic_id,
    "supplementalSemanticIds": _ReaderAndSetterForReferenceElement.read_and_set_supplemental_semantic_ids,
    "qualifiers": _ReaderAndSetterForReferenceElement.read_and_set_qualifiers,
    "embeddedDataSpecifications": _ReaderAndSetterForReferenceElement.read_and_set_embedded_data_specifications,
    "value": _ReaderAndSetterForReferenceElement.read_and_set_value,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForBlob`
_READ_AND_SET_DISPATCH_FOR_BLOB: Mapping[
    str,
    Callable[[_ReaderAndSetterForBlob, Element, Iterator[Tuple[str, Element]]], None],
] = {
    "extensions": _ReaderAndSetterForBlob.read_and_set_extensions,
    "category": _ReaderAndSetterForBlob.read_and_set_category,
    "idShort": _ReaderAndSetterForBlob.read_and_set_id_short,
    "displayName": _ReaderAndSetterForBlob.read_and_set_display_name,
    "description": _ReaderAndSetterForBlob.read_and_set_description,
    "semanticId": _ReaderAndSetterForBlob.read_and_set_semantic_id,
    "supplementalSemanticIds": _ReaderAndSetterForBlob.read_and_set_supplemental_semantic_ids,
    "qualifiers": _ReaderAndSetterForBlob.read_and_set_qualifiers,
    "embeddedDataSpecifications": _ReaderAndSetterForBlob.read_and_set_embedded_data_specifications,
    "value": _ReaderAndSetterForBlob.read_and_set_value,
    "contentType": _ReaderAndSetterForBlob.read_and_set_content_type,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForFile`
_READ_AND_SET_DISPATCH_FOR_FILE: Mapping[
    str,
    Callable[[_ReaderAndSetterForFile, Element, Iterator[Tuple[str, Element]]], None],
] = {
    "extensions": _ReaderAndSetterForFile.read_and_set_extensions,
    "category": _ReaderAndSetterForFile.read_and_set_category,
    "idShort": _ReaderAndSetterForFile.read_and_set_id_short,
    "displayName": _ReaderAndSetterForFile.read_and_set_display_name,
    "description": _ReaderAndSetterForFile.read_and_set_description,
    "semanticId": _ReaderAndSetterForFile.read_and_set_semantic_id,
    "supplementalSemanticIds": _ReaderAndSetterForFile.read_and_set_supplemental_semantic_ids,
    "qualifiers": _ReaderAndSetterForFile.read_and_set_qualifiers,
    "embeddedDataSpecifications": _ReaderAndSetterForFile.read_and_set_embedded_data_specifications,
    "value": _ReaderAndSetterForFile.read_and_set_value,
    "contentType": _ReaderAndSetterForFile.read_and_set_content_type,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForAnnotatedRelationshipElement`
_READ_AND_SET_DISPATCH_FOR_ANNOTATED_RELATIONSHIP_ELEMENT: Mapping[
    str,
    Callable[
        [
            _ReaderAndSetterForAnnotatedRelationshipElement,
            Element,
            Iterator[Tuple[str, Element]],
        ],
        None,
    ],
] = {
    "extensions": _ReaderAndSetterForAnnotatedRelationshipElement.read_and_set_extensions,
    "category": _ReaderAndSetterForAnnotatedRelationshipElement.read_and_set_category,
    "idShort": _ReaderAndSetterForAnnotatedRelationshipElement.read_and_set_id_short,
    "displayName": _ReaderAndSetterForAnnotatedRelationshipElement.read_and_set_display_name,
    "description": _ReaderAndSetterForAnnotatedRelationshipElement.read_and_set_description,
    "semanticId": _ReaderAndSetterForAnnotatedRelationshipElement.read_and_set_semantic_id,
    "supplementalSemanticIds": _ReaderAndSetterForAnnotatedRelationshipElement.read_and_set_supplemental_semantic_ids,
    "qualifiers": _ReaderAndSetterForAnnotatedRelationshipElement.read_and_set_qualifiers,
    "embeddedDataSpecifications": _ReaderAndSetterForAnnotatedRelationshipElement.read_and_set_embedded_data_specifications,
    "first": _ReaderAndSetterForAnnotatedRelationshipElement.read_and_set_first,
    "second": _ReaderAndSetterForAnnotatedRelationshipElement.read_and_set_second,
    "annotations": _ReaderAndSetterForAnnotatedRelationshipElement.read_and_set_annotations,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForEntity`
_READ_AND_SET_DISPATCH_FOR_ENTITY: Mapping[
    str,
    Callable[[_ReaderAndSetterForEntity, Element, Iterator[Tuple[str, Element]]], None],
] = {
    "extensions": _ReaderAndSetterForEntity.read_and_set_extensions,
    "category": _ReaderAndSetterForEntity.read_and_set_category,
    "idShort": _ReaderAndSetterForEntity.read_and_set_id_short,
    "displayName": _ReaderAndSetterForEntity.read_and_set_display_name,
    "description": _ReaderAndSetterForEntity.read_and_set_description,
    "semanticId": _ReaderAndSetterForEntity.read_and_set_semantic_id,
    "supplementalSemanticIds": _ReaderAndSetterForEntity.read_and_set_supplemental_semantic_ids,
    "qualifiers": _ReaderAndSetterForEntity.read_and_set_qualifiers,
    "embeddedDataSpecifications": _ReaderAndSetterForEntity.read_and_set_embedded_data_specifications,
    "statements": _ReaderAndSetterForEntity.read_and_set_statements,
    "entityType": _ReaderAndSetterForEntity.read_and_set_entity_type,
    "globalAssetId": _ReaderAndSetterForEntity.read_and_set_global_asset_id,
    "specificAssetIds": _ReaderAndSetterForEntity.read_and_set_specific_asset_ids,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForEventPayload`
_READ_AND_SET_DISPATCH_FOR_EVENT_PAYLOAD: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForEventPayload, Element, Iterator[Tuple[str, Element]]], None
    ],
] = {
    "source": _ReaderAndSetterForEventPayload.read_and_set_source,
    "sourceSemanticId": _ReaderAndSetterForEventPayload.read_and_set_source_semantic_id,
    "observableReference": _ReaderAndSetterForEventPayload.read_and_set_observable_reference,
    "observableSemanticId": _ReaderAndSetterForEventPayload.read_and_set_observable_semantic_id,
    "topic": _ReaderAndSetterForEventPayload.read_and_set_topic,
    "subjectId": _ReaderAndSetterForEventPayload.read_and_set_subject_id,
    "timeStamp": _ReaderAndSetterForEventPayload.read_and_set_time_stamp,
    "payload": _ReaderAndSetterForEventPayload.read_and_set_payload,
}


#: Dispatch XML class names to read-as-sequence functions
#: corresponding to concrete descendants of EventElement
_DISPATCH_FOR_EVENT_ELEMENT: Mapping[
    str, Callable[[Element, Iterator[Tuple[str, Element]]], aas_types.EventElement]
] = {
    "basicEventElement": _read_basic_event_element_as_sequence,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForBasicEventElement`
_READ_AND_SET_DISPATCH_FOR_BASIC_EVENT_ELEMENT: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForBasicEventElement, Element, Iterator[Tuple[str, Element]]],
        None,
    ],
] = {
    "extensions": _ReaderAndSetterForBasicEventElement.read_and_set_extensions,
    "category": _ReaderAndSetterForBasicEventElement.read_and_set_category,
    "idShort": _ReaderAndSetterForBasicEventElement.read_and_set_id_short,
    "displayName": _ReaderAndSetterForBasicEventElement.read_and_set_display_name,
    "description": _ReaderAndSetterForBasicEventElement.read_and_set_description,
    "semanticId": _ReaderAndSetterForBasicEventElement.read_and_set_semantic_id,
    "supplementalSemanticIds": _ReaderAndSetterForBasicEventElement.read_and_set_supplemental_semantic_ids,
    "qualifiers": _ReaderAndSetterForBasicEventElement.read_and_set_qualifiers,
    "embeddedDataSpecifications": _ReaderAndSetterForBasicEventElement.read_and_set_embedded_data_specifications,
    "observed": _ReaderAndSetterForBasicEventElement.read_and_set_observed,
    "direction": _ReaderAndSetterForBasicEventElement.read_and_set_direction,
    "state": _ReaderAndSetterForBasicEventElement.read_and_set_state,
    "messageTopic": _ReaderAndSetterForBasicEventElement.read_and_set_message_topic,
    "messageBroker": _ReaderAndSetterForBasicEventElement.read_and_set_message_broker,
    "lastUpdate": _ReaderAndSetterForBasicEventElement.read_and_set_last_update,
    "minInterval": _ReaderAndSetterForBasicEventElement.read_and_set_min_interval,
    "maxInterval": _ReaderAndSetterForBasicEventElement.read_and_set_max_interval,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForOperation`
_READ_AND_SET_DISPATCH_FOR_OPERATION: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForOperation, Element, Iterator[Tuple[str, Element]]], None
    ],
] = {
    "extensions": _ReaderAndSetterForOperation.read_and_set_extensions,
    "category": _ReaderAndSetterForOperation.read_and_set_category,
    "idShort": _ReaderAndSetterForOperation.read_and_set_id_short,
    "displayName": _ReaderAndSetterForOperation.read_and_set_display_name,
    "description": _ReaderAndSetterForOperation.read_and_set_description,
    "semanticId": _ReaderAndSetterForOperation.read_and_set_semantic_id,
    "supplementalSemanticIds": _ReaderAndSetterForOperation.read_and_set_supplemental_semantic_ids,
    "qualifiers": _ReaderAndSetterForOperation.read_and_set_qualifiers,
    "embeddedDataSpecifications": _ReaderAndSetterForOperation.read_and_set_embedded_data_specifications,
    "inputVariables": _ReaderAndSetterForOperation.read_and_set_input_variables,
    "outputVariables": _ReaderAndSetterForOperation.read_and_set_output_variables,
    "inoutputVariables": _ReaderAndSetterForOperation.read_and_set_inoutput_variables,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForOperationVariable`
_READ_AND_SET_DISPATCH_FOR_OPERATION_VARIABLE: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForOperationVariable, Element, Iterator[Tuple[str, Element]]],
        None,
    ],
] = {
    "value": _ReaderAndSetterForOperationVariable.read_and_set_value,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForCapability`
_READ_AND_SET_DISPATCH_FOR_CAPABILITY: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForCapability, Element, Iterator[Tuple[str, Element]]], None
    ],
] = {
    "extensions": _ReaderAndSetterForCapability.read_and_set_extensions,
    "category": _ReaderAndSetterForCapability.read_and_set_category,
    "idShort": _ReaderAndSetterForCapability.read_and_set_id_short,
    "displayName": _ReaderAndSetterForCapability.read_and_set_display_name,
    "description": _ReaderAndSetterForCapability.read_and_set_description,
    "semanticId": _ReaderAndSetterForCapability.read_and_set_semantic_id,
    "supplementalSemanticIds": _ReaderAndSetterForCapability.read_and_set_supplemental_semantic_ids,
    "qualifiers": _ReaderAndSetterForCapability.read_and_set_qualifiers,
    "embeddedDataSpecifications": _ReaderAndSetterForCapability.read_and_set_embedded_data_specifications,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForConceptDescription`
_READ_AND_SET_DISPATCH_FOR_CONCEPT_DESCRIPTION: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForConceptDescription, Element, Iterator[Tuple[str, Element]]],
        None,
    ],
] = {
    "extensions": _ReaderAndSetterForConceptDescription.read_and_set_extensions,
    "category": _ReaderAndSetterForConceptDescription.read_and_set_category,
    "idShort": _ReaderAndSetterForConceptDescription.read_and_set_id_short,
    "displayName": _ReaderAndSetterForConceptDescription.read_and_set_display_name,
    "description": _ReaderAndSetterForConceptDescription.read_and_set_description,
    "administration": _ReaderAndSetterForConceptDescription.read_and_set_administration,
    "id": _ReaderAndSetterForConceptDescription.read_and_set_id,
    "embeddedDataSpecifications": _ReaderAndSetterForConceptDescription.read_and_set_embedded_data_specifications,
    "isCaseOf": _ReaderAndSetterForConceptDescription.read_and_set_is_case_of,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForReference`
_READ_AND_SET_DISPATCH_FOR_REFERENCE: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForReference, Element, Iterator[Tuple[str, Element]]], None
    ],
] = {
    "type": _ReaderAndSetterForReference.read_and_set_type,
    "referredSemanticId": _ReaderAndSetterForReference.read_and_set_referred_semantic_id,
    "keys": _ReaderAndSetterForReference.read_and_set_keys,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForKey`
_READ_AND_SET_DISPATCH_FOR_KEY: Mapping[
    str,
    Callable[[_ReaderAndSetterForKey, Element, Iterator[Tuple[str, Element]]], None],
] = {
    "type": _ReaderAndSetterForKey.read_and_set_type,
    "value": _ReaderAndSetterForKey.read_and_set_value,
}


#: Dispatch XML class names to read-as-sequence functions
#: corresponding to concrete descendants of AbstractLangString
_DISPATCH_FOR_ABSTRACT_LANG_STRING: Mapping[
    str,
    Callable[[Element, Iterator[Tuple[str, Element]]], aas_types.AbstractLangString],
] = {
    "langStringDefinitionTypeIec61360": _read_lang_string_definition_type_iec_61360_as_sequence,
    "langStringNameType": _read_lang_string_name_type_as_sequence,
    "langStringPreferredNameTypeIec61360": _read_lang_string_preferred_name_type_iec_61360_as_sequence,
    "langStringShortNameTypeIec61360": _read_lang_string_short_name_type_iec_61360_as_sequence,
    "langStringTextType": _read_lang_string_text_type_as_sequence,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForLangStringNameType`
_READ_AND_SET_DISPATCH_FOR_LANG_STRING_NAME_TYPE: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForLangStringNameType, Element, Iterator[Tuple[str, Element]]],
        None,
    ],
] = {
    "language": _ReaderAndSetterForLangStringNameType.read_and_set_language,
    "text": _ReaderAndSetterForLangStringNameType.read_and_set_text,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForLangStringTextType`
_READ_AND_SET_DISPATCH_FOR_LANG_STRING_TEXT_TYPE: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForLangStringTextType, Element, Iterator[Tuple[str, Element]]],
        None,
    ],
] = {
    "language": _ReaderAndSetterForLangStringTextType.read_and_set_language,
    "text": _ReaderAndSetterForLangStringTextType.read_and_set_text,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForEnvironment`
_READ_AND_SET_DISPATCH_FOR_ENVIRONMENT: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForEnvironment, Element, Iterator[Tuple[str, Element]]], None
    ],
] = {
    "assetAdministrationShells": _ReaderAndSetterForEnvironment.read_and_set_asset_administration_shells,
    "submodels": _ReaderAndSetterForEnvironment.read_and_set_submodels,
    "conceptDescriptions": _ReaderAndSetterForEnvironment.read_and_set_concept_descriptions,
}


#: Dispatch XML class names to read-as-sequence functions
#: corresponding to concrete descendants of DataSpecificationContent
_DISPATCH_FOR_DATA_SPECIFICATION_CONTENT: Mapping[
    str,
    Callable[
        [Element, Iterator[Tuple[str, Element]]], aas_types.DataSpecificationContent
    ],
] = {
    "dataSpecificationIec61360": _read_data_specification_iec_61360_as_sequence,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForEmbeddedDataSpecification`
_READ_AND_SET_DISPATCH_FOR_EMBEDDED_DATA_SPECIFICATION: Mapping[
    str,
    Callable[
        [
            _ReaderAndSetterForEmbeddedDataSpecification,
            Element,
            Iterator[Tuple[str, Element]],
        ],
        None,
    ],
] = {
    "dataSpecification": _ReaderAndSetterForEmbeddedDataSpecification.read_and_set_data_specification,
    "dataSpecificationContent": _ReaderAndSetterForEmbeddedDataSpecification.read_and_set_data_specification_content,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForLevelType`
_READ_AND_SET_DISPATCH_FOR_LEVEL_TYPE: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForLevelType, Element, Iterator[Tuple[str, Element]]], None
    ],
] = {
    "min": _ReaderAndSetterForLevelType.read_and_set_min,
    "nom": _ReaderAndSetterForLevelType.read_and_set_nom,
    "typ": _ReaderAndSetterForLevelType.read_and_set_typ,
    "max": _ReaderAndSetterForLevelType.read_and_set_max,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForValueReferencePair`
_READ_AND_SET_DISPATCH_FOR_VALUE_REFERENCE_PAIR: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForValueReferencePair, Element, Iterator[Tuple[str, Element]]],
        None,
    ],
] = {
    "value": _ReaderAndSetterForValueReferencePair.read_and_set_value,
    "valueId": _ReaderAndSetterForValueReferencePair.read_and_set_value_id,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForValueList`
_READ_AND_SET_DISPATCH_FOR_VALUE_LIST: Mapping[
    str,
    Callable[
        [_ReaderAndSetterForValueList, Element, Iterator[Tuple[str, Element]]], None
    ],
] = {
    "valueReferencePairs": _ReaderAndSetterForValueList.read_and_set_value_reference_pairs,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForLangStringPreferredNameTypeIEC61360`
_READ_AND_SET_DISPATCH_FOR_LANG_STRING_PREFERRED_NAME_TYPE_IEC_61360: Mapping[
    str,
    Callable[
        [
            _ReaderAndSetterForLangStringPreferredNameTypeIEC61360,
            Element,
            Iterator[Tuple[str, Element]],
        ],
        None,
    ],
] = {
    "language": _ReaderAndSetterForLangStringPreferredNameTypeIEC61360.read_and_set_language,
    "text": _ReaderAndSetterForLangStringPreferredNameTypeIEC61360.read_and_set_text,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForLangStringShortNameTypeIEC61360`
_READ_AND_SET_DISPATCH_FOR_LANG_STRING_SHORT_NAME_TYPE_IEC_61360: Mapping[
    str,
    Callable[
        [
            _ReaderAndSetterForLangStringShortNameTypeIEC61360,
            Element,
            Iterator[Tuple[str, Element]],
        ],
        None,
    ],
] = {
    "language": _ReaderAndSetterForLangStringShortNameTypeIEC61360.read_and_set_language,
    "text": _ReaderAndSetterForLangStringShortNameTypeIEC61360.read_and_set_text,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForLangStringDefinitionTypeIEC61360`
_READ_AND_SET_DISPATCH_FOR_LANG_STRING_DEFINITION_TYPE_IEC_61360: Mapping[
    str,
    Callable[
        [
            _ReaderAndSetterForLangStringDefinitionTypeIEC61360,
            Element,
            Iterator[Tuple[str, Element]],
        ],
        None,
    ],
] = {
    "language": _ReaderAndSetterForLangStringDefinitionTypeIEC61360.read_and_set_language,
    "text": _ReaderAndSetterForLangStringDefinitionTypeIEC61360.read_and_set_text,
}


#: Dispatch XML property name to read & set method in
#: :py:class:`_ReaderAndSetterForDataSpecificationIEC61360`
_READ_AND_SET_DISPATCH_FOR_DATA_SPECIFICATION_IEC_61360: Mapping[
    str,
    Callable[
        [
            _ReaderAndSetterForDataSpecificationIEC61360,
            Element,
            Iterator[Tuple[str, Element]],
        ],
        None,
    ],
] = {
    "preferredName": _ReaderAndSetterForDataSpecificationIEC61360.read_and_set_preferred_name,
    "shortName": _ReaderAndSetterForDataSpecificationIEC61360.read_and_set_short_name,
    "unit": _ReaderAndSetterForDataSpecificationIEC61360.read_and_set_unit,
    "unitId": _ReaderAndSetterForDataSpecificationIEC61360.read_and_set_unit_id,
    "sourceOfDefinition": _ReaderAndSetterForDataSpecificationIEC61360.read_and_set_source_of_definition,
    "symbol": _ReaderAndSetterForDataSpecificationIEC61360.read_and_set_symbol,
    "dataType": _ReaderAndSetterForDataSpecificationIEC61360.read_and_set_data_type,
    "definition": _ReaderAndSetterForDataSpecificationIEC61360.read_and_set_definition,
    "valueFormat": _ReaderAndSetterForDataSpecificationIEC61360.read_and_set_value_format,
    "valueList": _ReaderAndSetterForDataSpecificationIEC61360.read_and_set_value_list,
    "value": _ReaderAndSetterForDataSpecificationIEC61360.read_and_set_value,
    "levelType": _ReaderAndSetterForDataSpecificationIEC61360.read_and_set_level_type,
}


#: Dispatch XML class names to read-as-sequence functions
#: corresponding to the concrete classes
_GENERAL_DISPATCH: Mapping[
    str, Callable[[Element, Iterator[Tuple[str, Element]]], aas_types.Class]
] = {
    "extension": _read_extension_as_sequence,
    "administrativeInformation": _read_administrative_information_as_sequence,
    "qualifier": _read_qualifier_as_sequence,
    "assetAdministrationShell": _read_asset_administration_shell_as_sequence,
    "assetInformation": _read_asset_information_as_sequence,
    "resource": _read_resource_as_sequence,
    "specificAssetId": _read_specific_asset_id_as_sequence,
    "submodel": _read_submodel_as_sequence,
    "relationshipElement": _read_relationship_element_as_sequence,
    "submodelElementList": _read_submodel_element_list_as_sequence,
    "submodelElementCollection": _read_submodel_element_collection_as_sequence,
    "property": _read_property_as_sequence,
    "multiLanguageProperty": _read_multi_language_property_as_sequence,
    "range": _read_range_as_sequence,
    "referenceElement": _read_reference_element_as_sequence,
    "blob": _read_blob_as_sequence,
    "file": _read_file_as_sequence,
    "annotatedRelationshipElement": _read_annotated_relationship_element_as_sequence,
    "entity": _read_entity_as_sequence,
    "eventPayload": _read_event_payload_as_sequence,
    "basicEventElement": _read_basic_event_element_as_sequence,
    "operation": _read_operation_as_sequence,
    "operationVariable": _read_operation_variable_as_sequence,
    "capability": _read_capability_as_sequence,
    "conceptDescription": _read_concept_description_as_sequence,
    "reference": _read_reference_as_sequence,
    "key": _read_key_as_sequence,
    "langStringNameType": _read_lang_string_name_type_as_sequence,
    "langStringTextType": _read_lang_string_text_type_as_sequence,
    "environment": _read_environment_as_sequence,
    "embeddedDataSpecification": _read_embedded_data_specification_as_sequence,
    "levelType": _read_level_type_as_sequence,
    "valueReferencePair": _read_value_reference_pair_as_sequence,
    "valueList": _read_value_list_as_sequence,
    "langStringPreferredNameTypeIec61360": _read_lang_string_preferred_name_type_iec_61360_as_sequence,
    "langStringShortNameTypeIec61360": _read_lang_string_short_name_type_iec_61360_as_sequence,
    "langStringDefinitionTypeIec61360": _read_lang_string_definition_type_iec_61360_as_sequence,
    "dataSpecificationIec61360": _read_data_specification_iec_61360_as_sequence,
}


# endregion


# region Serialization


class _Serializer(aas_types.AbstractVisitor):
    """Encode instances as XML and write them to :py:attr:`~stream`."""

    #: Stream to be written to when we visit the instances
    stream: Final[TextIO]

    #: Method pointer to be invoked for writing the start element with or without
    #: specifying a namespace (depending on the state of the serializer)
    _write_start_element: Callable[[str], None]

    #: Method pointer to be invoked for writing an empty element with or without
    #: specifying a namespace (depending on the state of the serializer)
    _write_empty_element: Callable[[str], None]

    # NOTE (mristin, 2022-10-14):
    # The serialization procedure is quite rigid. We leverage the specifics of
    # the serialization procedure to optimize the code a bit.
    #
    # Namely, we model the writing of the XML elements as a state machine.
    # The namespace is only specified for the very first element. All the subsequent
    # elements will *not* have the namespace specified. We implement that behavior by
    # using pointers to methods, as Python treats the methods as first-class citizens.
    #
    # The ``_write_start_element`` will point to
    # ``_write_first_start_element_with_namespace`` on the *first* invocation.
    # Afterwards, it will be redirected to ``_write_start_element_without_namespace``.
    #
    # Analogously for ``_write_empty_element``.
    #
    # Please see the implementation for the details, but this should give you at least
    # a rough overview.

    def _write_first_start_element_with_namespace(self, name: str) -> None:
        """
        Write the start element with the tag name :paramref:`name` and specify
        its namespace.

        The :py:attr:`~_write_start_element` is set to
        :py:meth:`~_write_start_element_without_namespace` after the first invocation
        of this method.

        :param name: of the element tag. Expected to contain no XML special characters.
        """
        self.stream.write(f'<{name} xmlns="{NAMESPACE}">')

        # NOTE (mristin, 2022-10-14):
        # Any subsequence call to `_write_start_element` or `_write_empty_element`
        # should not specify the namespace of the element as we specified now already
        # specified it.
        self._write_start_element = self._write_start_element_without_namespace
        self._write_empty_element = self._write_empty_element_without_namespace

    def _write_start_element_without_namespace(self, name: str) -> None:
        """
        Write the start element with the tag name :paramref:`name`.

        The first element, written *before* this one, is expected to have been
        already written with the namespace specified.

        :param name: of the element tag. Expected to contain no XML special characters.
        """
        self.stream.write(f"<{name}>")

    def _escape_and_write_text(self, text: str) -> None:
        """
        Escape :paramref:`text` for XML and write it.

        :param text: to be escaped and written
        """
        # NOTE (mristin, 2022-10-14):
        # We ran ``timeit`` on manual code which escaped XML special characters with
        # a dictionary, and on another snippet which called three ``.replace()``.
        # The code with ``.replace()`` was an order of magnitude faster on our computers.
        self.stream.write(
            text.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
        )

    def _write_end_element(self, name: str) -> None:
        """
        Write the end element with the tag name :paramref:`name`.

        :param name: of the element tag. Expected to contain no XML special characters.
        """
        self.stream.write(f"</{name}>")

    def _write_first_empty_element_with_namespace(self, name: str) -> None:
        """
        Write the first (and only) empty element with the tag name :paramref:`name`.

        No elements are expected to be written to the stream afterwards. The element
        includes the namespace specification.

        :param name: of the element tag. Expected to contain no XML special characters.
        """
        self.stream.write(f'<{name} xmlns="{NAMESPACE}"/>')
        self._write_empty_element = self._rase_if_write_element_called_again
        self._write_start_element = self._rase_if_write_element_called_again

    def _rase_if_write_element_called_again(self, name: str) -> None:
        raise AssertionError(
            f"We expected to call ``_write_first_empty_element_with_namespace`` "
            f"only once. This is an unexpected second call for writing "
            f"an (empty or non-empty) element with the tag name: {name!r}"
        )

    def _write_empty_element_without_namespace(self, name: str) -> None:
        """
        Write the empty element with the tag name :paramref:`name`.

        The call to this method is expected to occur *after* the enclosing element with
        a specified namespace has been written.

        :param name: of the element tag. Expected to contain no XML special characters.
        """
        self.stream.write(f"<{name}/>")

    def _write_bool_property(self, name: str, value: bool) -> None:
        """
        Write the :paramref:`value` of a boolean property enclosed in
        the :paramref:`name` element.

        :param name: of the corresponding element tag
        :param value: of the property
        """
        self._write_start_element(name)
        self.stream.write("true" if value else "false")
        self._write_end_element(name)

    def _write_int_property(self, name: str, value: int) -> None:
        """
        Write the :paramref:`value` of an integer property enclosed in
        the :paramref:`name` element.

        :param name: of the corresponding element tag
        :param value: of the property
        """
        self._write_start_element(name)
        self.stream.write(str(value))
        self._write_end_element(name)

    def _write_float_property(self, name: str, value: float) -> None:
        """
        Write the :paramref:`value` of a floating-point property enclosed in
        the :paramref:`name` element.

        :param name: of the corresponding element tag
        :param value: of the property
        """
        self._write_start_element(name)

        if value == math.inf:
            self.stream.write("INF")
        elif value == -math.inf:
            self.stream.write("-INF")
        elif math.isnan(value):
            self.stream.write("NaN")
        elif value == 0:
            if math.copysign(1.0, value) < 0.0:
                self.stream.write("-0.0")
            else:
                self.stream.write("0.0")
        else:
            self.stream.write(str(value))

    def _write_str_property(self, name: str, value: str) -> None:
        """
        Write the :paramref:`value` of a string property enclosed in
        the :paramref:`name` element.

        :param name: of the corresponding element tag
        :param value: of the property
        """
        self._write_start_element(name)
        self._escape_and_write_text(value)
        self._write_end_element(name)

    def _write_bytes_property(self, name: str, value: bytes) -> None:
        """
        Write the :paramref:`value` of a binary-content property enclosed in
        the :paramref:`name` element.

        :param name: of the corresponding element tag
        :param value: of the property
        """
        self._write_start_element(name)

        # NOTE (mristin, 2022-10-14):
        # We need to decode the result of the base64-encoding to ASCII since we are
        # writing to an XML *text* stream. ``base64.b64encode(.)`` gives us bytes,
        # not a string.
        encoded = base64.b64encode(value).decode("ascii")

        # NOTE (mristin, 2022-10-14):
        # Base64 alphabet excludes ``<``, ``>`` and ``&``, so we can directly
        # write the ``encoded`` content to the stream as XML text.
        #
        # See: https://datatracker.ietf.org/doc/html/rfc4648#section-4
        self.stream.write(encoded)
        self._write_end_element(name)

    def __init__(self, stream: TextIO) -> None:
        """
        Initialize the visitor to write to :paramref:`stream`.

        The first element will include the :py:attr:`~.NAMESPACE`. Every other
        element will not have the namespace specified.

        :param stream: where to write to
        """
        self.stream = stream
        self._write_start_element = self._write_first_start_element_with_namespace
        self._write_empty_element = self._write_first_empty_element_with_namespace

    def _write_extension_as_sequence(self, that: aas_types.Extension) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.semantic_id is not None:
            self._write_start_element("semanticId")
            self._write_reference_as_sequence(that.semantic_id)
            self._write_end_element("semanticId")

        if that.supplemental_semantic_ids is not None:
            if len(that.supplemental_semantic_ids) == 0:
                self._write_empty_element("supplementalSemanticIds")
            else:
                self._write_start_element("supplementalSemanticIds")
                for an_item in that.supplemental_semantic_ids:
                    self.visit(an_item)
                self._write_end_element("supplementalSemanticIds")

        self._write_str_property("name", that.name)

        if that.value_type is not None:
            self._write_str_property("valueType", that.value_type.value)

        if that.value is not None:
            self._write_str_property("value", that.value)

        if that.refers_to is not None:
            if len(that.refers_to) == 0:
                self._write_empty_element("refersTo")
            else:
                self._write_start_element("refersTo")
                for another_item in that.refers_to:
                    self.visit(another_item)
                self._write_end_element("refersTo")

    def visit_extension(self, that: aas_types.Extension) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("extension")
        self._write_extension_as_sequence(that)
        self._write_end_element("extension")

    def _write_administrative_information_as_sequence(
        self, that: aas_types.AdministrativeInformation
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.embedded_data_specifications is not None:
            if len(that.embedded_data_specifications) == 0:
                self._write_empty_element("embeddedDataSpecifications")
            else:
                self._write_start_element("embeddedDataSpecifications")
                for an_item in that.embedded_data_specifications:
                    self.visit(an_item)
                self._write_end_element("embeddedDataSpecifications")

        if that.version is not None:
            self._write_str_property("version", that.version)

        if that.revision is not None:
            self._write_str_property("revision", that.revision)

        if that.creator is not None:
            self._write_start_element("creator")
            self._write_reference_as_sequence(that.creator)
            self._write_end_element("creator")

        if that.template_id is not None:
            self._write_str_property("templateId", that.template_id)

    def visit_administrative_information(
        self, that: aas_types.AdministrativeInformation
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        # We optimize for the case where all the optional properties are not set,
        # so that we can simply output an empty element.
        if (
            that.embedded_data_specifications is None
            and that.version is None
            and that.revision is None
            and that.creator is None
            and that.template_id is None
        ):
            self._write_empty_element("administrativeInformation")
        else:
            self._write_start_element("administrativeInformation")
            self._write_administrative_information_as_sequence(that)
            self._write_end_element("administrativeInformation")

    def _write_qualifier_as_sequence(self, that: aas_types.Qualifier) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.semantic_id is not None:
            self._write_start_element("semanticId")
            self._write_reference_as_sequence(that.semantic_id)
            self._write_end_element("semanticId")

        if that.supplemental_semantic_ids is not None:
            if len(that.supplemental_semantic_ids) == 0:
                self._write_empty_element("supplementalSemanticIds")
            else:
                self._write_start_element("supplementalSemanticIds")
                for an_item in that.supplemental_semantic_ids:
                    self.visit(an_item)
                self._write_end_element("supplementalSemanticIds")

        if that.kind is not None:
            self._write_str_property("kind", that.kind.value)

        self._write_str_property("type", that.type)

        self._write_str_property("valueType", that.value_type.value)

        if that.value is not None:
            self._write_str_property("value", that.value)

        if that.value_id is not None:
            self._write_start_element("valueId")
            self._write_reference_as_sequence(that.value_id)
            self._write_end_element("valueId")

    def visit_qualifier(self, that: aas_types.Qualifier) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("qualifier")
        self._write_qualifier_as_sequence(that)
        self._write_end_element("qualifier")

    def _write_asset_administration_shell_as_sequence(
        self, that: aas_types.AssetAdministrationShell
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.extensions is not None:
            if len(that.extensions) == 0:
                self._write_empty_element("extensions")
            else:
                self._write_start_element("extensions")
                for an_item in that.extensions:
                    self.visit(an_item)
                self._write_end_element("extensions")

        if that.category is not None:
            self._write_str_property("category", that.category)

        if that.id_short is not None:
            self._write_str_property("idShort", that.id_short)

        if that.display_name is not None:
            if len(that.display_name) == 0:
                self._write_empty_element("displayName")
            else:
                self._write_start_element("displayName")
                for another_item in that.display_name:
                    self.visit(another_item)
                self._write_end_element("displayName")

        if that.description is not None:
            if len(that.description) == 0:
                self._write_empty_element("description")
            else:
                self._write_start_element("description")
                for yet_another_item in that.description:
                    self.visit(yet_another_item)
                self._write_end_element("description")

        if that.administration is not None:
            the_administration = that.administration
            # We optimize for the case where all the optional properties are not set,
            # so that we can simply output an empty element.
            if (
                the_administration.embedded_data_specifications is None
                and the_administration.version is None
                and the_administration.revision is None
                and the_administration.creator is None
                and the_administration.template_id is None
            ):
                self._write_empty_element("administration")
            else:
                self._write_start_element("administration")
                self._write_administrative_information_as_sequence(the_administration)
                self._write_end_element("administration")

        self._write_str_property("id", that.id)

        if that.embedded_data_specifications is not None:
            if len(that.embedded_data_specifications) == 0:
                self._write_empty_element("embeddedDataSpecifications")
            else:
                self._write_start_element("embeddedDataSpecifications")
                for yet_yet_another_item in that.embedded_data_specifications:
                    self.visit(yet_yet_another_item)
                self._write_end_element("embeddedDataSpecifications")

        if that.derived_from is not None:
            self._write_start_element("derivedFrom")
            self._write_reference_as_sequence(that.derived_from)
            self._write_end_element("derivedFrom")

        self._write_start_element("assetInformation")
        self._write_asset_information_as_sequence(that.asset_information)
        self._write_end_element("assetInformation")

        if that.submodels is not None:
            if len(that.submodels) == 0:
                self._write_empty_element("submodels")
            else:
                self._write_start_element("submodels")
                for yet_yet_yet_another_item in that.submodels:
                    self.visit(yet_yet_yet_another_item)
                self._write_end_element("submodels")

    def visit_asset_administration_shell(
        self, that: aas_types.AssetAdministrationShell
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("assetAdministrationShell")
        self._write_asset_administration_shell_as_sequence(that)
        self._write_end_element("assetAdministrationShell")

    def _write_asset_information_as_sequence(
        self, that: aas_types.AssetInformation
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        self._write_str_property("assetKind", that.asset_kind.value)

        if that.global_asset_id is not None:
            self._write_str_property("globalAssetId", that.global_asset_id)

        if that.specific_asset_ids is not None:
            if len(that.specific_asset_ids) == 0:
                self._write_empty_element("specificAssetIds")
            else:
                self._write_start_element("specificAssetIds")
                for an_item in that.specific_asset_ids:
                    self.visit(an_item)
                self._write_end_element("specificAssetIds")

        if that.asset_type is not None:
            self._write_str_property("assetType", that.asset_type)

        if that.default_thumbnail is not None:
            self._write_start_element("defaultThumbnail")
            self._write_resource_as_sequence(that.default_thumbnail)
            self._write_end_element("defaultThumbnail")

    def visit_asset_information(self, that: aas_types.AssetInformation) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("assetInformation")
        self._write_asset_information_as_sequence(that)
        self._write_end_element("assetInformation")

    def _write_resource_as_sequence(self, that: aas_types.Resource) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        self._write_str_property("path", that.path)

        if that.content_type is not None:
            self._write_str_property("contentType", that.content_type)

    def visit_resource(self, that: aas_types.Resource) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("resource")
        self._write_resource_as_sequence(that)
        self._write_end_element("resource")

    def _write_specific_asset_id_as_sequence(
        self, that: aas_types.SpecificAssetID
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.semantic_id is not None:
            self._write_start_element("semanticId")
            self._write_reference_as_sequence(that.semantic_id)
            self._write_end_element("semanticId")

        if that.supplemental_semantic_ids is not None:
            if len(that.supplemental_semantic_ids) == 0:
                self._write_empty_element("supplementalSemanticIds")
            else:
                self._write_start_element("supplementalSemanticIds")
                for an_item in that.supplemental_semantic_ids:
                    self.visit(an_item)
                self._write_end_element("supplementalSemanticIds")

        self._write_str_property("name", that.name)

        self._write_str_property("value", that.value)

        if that.external_subject_id is not None:
            self._write_start_element("externalSubjectId")
            self._write_reference_as_sequence(that.external_subject_id)
            self._write_end_element("externalSubjectId")

    def visit_specific_asset_id(self, that: aas_types.SpecificAssetID) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("specificAssetId")
        self._write_specific_asset_id_as_sequence(that)
        self._write_end_element("specificAssetId")

    def _write_submodel_as_sequence(self, that: aas_types.Submodel) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.extensions is not None:
            if len(that.extensions) == 0:
                self._write_empty_element("extensions")
            else:
                self._write_start_element("extensions")
                for an_item in that.extensions:
                    self.visit(an_item)
                self._write_end_element("extensions")

        if that.category is not None:
            self._write_str_property("category", that.category)

        if that.id_short is not None:
            self._write_str_property("idShort", that.id_short)

        if that.display_name is not None:
            if len(that.display_name) == 0:
                self._write_empty_element("displayName")
            else:
                self._write_start_element("displayName")
                for another_item in that.display_name:
                    self.visit(another_item)
                self._write_end_element("displayName")

        if that.description is not None:
            if len(that.description) == 0:
                self._write_empty_element("description")
            else:
                self._write_start_element("description")
                for yet_another_item in that.description:
                    self.visit(yet_another_item)
                self._write_end_element("description")

        if that.administration is not None:
            the_administration = that.administration
            # We optimize for the case where all the optional properties are not set,
            # so that we can simply output an empty element.
            if (
                the_administration.embedded_data_specifications is None
                and the_administration.version is None
                and the_administration.revision is None
                and the_administration.creator is None
                and the_administration.template_id is None
            ):
                self._write_empty_element("administration")
            else:
                self._write_start_element("administration")
                self._write_administrative_information_as_sequence(the_administration)
                self._write_end_element("administration")

        self._write_str_property("id", that.id)

        if that.kind is not None:
            self._write_str_property("kind", that.kind.value)

        if that.semantic_id is not None:
            self._write_start_element("semanticId")
            self._write_reference_as_sequence(that.semantic_id)
            self._write_end_element("semanticId")

        if that.supplemental_semantic_ids is not None:
            if len(that.supplemental_semantic_ids) == 0:
                self._write_empty_element("supplementalSemanticIds")
            else:
                self._write_start_element("supplementalSemanticIds")
                for yet_yet_another_item in that.supplemental_semantic_ids:
                    self.visit(yet_yet_another_item)
                self._write_end_element("supplementalSemanticIds")

        if that.qualifiers is not None:
            if len(that.qualifiers) == 0:
                self._write_empty_element("qualifiers")
            else:
                self._write_start_element("qualifiers")
                for yet_yet_yet_another_item in that.qualifiers:
                    self.visit(yet_yet_yet_another_item)
                self._write_end_element("qualifiers")

        if that.embedded_data_specifications is not None:
            if len(that.embedded_data_specifications) == 0:
                self._write_empty_element("embeddedDataSpecifications")
            else:
                self._write_start_element("embeddedDataSpecifications")
                for yet_yet_yet_yet_another_item in that.embedded_data_specifications:
                    self.visit(yet_yet_yet_yet_another_item)
                self._write_end_element("embeddedDataSpecifications")

        if that.submodel_elements is not None:
            if len(that.submodel_elements) == 0:
                self._write_empty_element("submodelElements")
            else:
                self._write_start_element("submodelElements")
                for yet_yet_yet_yet_yet_another_item in that.submodel_elements:
                    self.visit(yet_yet_yet_yet_yet_another_item)
                self._write_end_element("submodelElements")

    def visit_submodel(self, that: aas_types.Submodel) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("submodel")
        self._write_submodel_as_sequence(that)
        self._write_end_element("submodel")

    def _write_relationship_element_as_sequence(
        self, that: aas_types.RelationshipElement
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.extensions is not None:
            if len(that.extensions) == 0:
                self._write_empty_element("extensions")
            else:
                self._write_start_element("extensions")
                for an_item in that.extensions:
                    self.visit(an_item)
                self._write_end_element("extensions")

        if that.category is not None:
            self._write_str_property("category", that.category)

        if that.id_short is not None:
            self._write_str_property("idShort", that.id_short)

        if that.display_name is not None:
            if len(that.display_name) == 0:
                self._write_empty_element("displayName")
            else:
                self._write_start_element("displayName")
                for another_item in that.display_name:
                    self.visit(another_item)
                self._write_end_element("displayName")

        if that.description is not None:
            if len(that.description) == 0:
                self._write_empty_element("description")
            else:
                self._write_start_element("description")
                for yet_another_item in that.description:
                    self.visit(yet_another_item)
                self._write_end_element("description")

        if that.semantic_id is not None:
            self._write_start_element("semanticId")
            self._write_reference_as_sequence(that.semantic_id)
            self._write_end_element("semanticId")

        if that.supplemental_semantic_ids is not None:
            if len(that.supplemental_semantic_ids) == 0:
                self._write_empty_element("supplementalSemanticIds")
            else:
                self._write_start_element("supplementalSemanticIds")
                for yet_yet_another_item in that.supplemental_semantic_ids:
                    self.visit(yet_yet_another_item)
                self._write_end_element("supplementalSemanticIds")

        if that.qualifiers is not None:
            if len(that.qualifiers) == 0:
                self._write_empty_element("qualifiers")
            else:
                self._write_start_element("qualifiers")
                for yet_yet_yet_another_item in that.qualifiers:
                    self.visit(yet_yet_yet_another_item)
                self._write_end_element("qualifiers")

        if that.embedded_data_specifications is not None:
            if len(that.embedded_data_specifications) == 0:
                self._write_empty_element("embeddedDataSpecifications")
            else:
                self._write_start_element("embeddedDataSpecifications")
                for yet_yet_yet_yet_another_item in that.embedded_data_specifications:
                    self.visit(yet_yet_yet_yet_another_item)
                self._write_end_element("embeddedDataSpecifications")

        self._write_start_element("first")
        self._write_reference_as_sequence(that.first)
        self._write_end_element("first")

        self._write_start_element("second")
        self._write_reference_as_sequence(that.second)
        self._write_end_element("second")

    def visit_relationship_element(self, that: aas_types.RelationshipElement) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("relationshipElement")
        self._write_relationship_element_as_sequence(that)
        self._write_end_element("relationshipElement")

    def _write_submodel_element_list_as_sequence(
        self, that: aas_types.SubmodelElementList
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.extensions is not None:
            if len(that.extensions) == 0:
                self._write_empty_element("extensions")
            else:
                self._write_start_element("extensions")
                for an_item in that.extensions:
                    self.visit(an_item)
                self._write_end_element("extensions")

        if that.category is not None:
            self._write_str_property("category", that.category)

        if that.id_short is not None:
            self._write_str_property("idShort", that.id_short)

        if that.display_name is not None:
            if len(that.display_name) == 0:
                self._write_empty_element("displayName")
            else:
                self._write_start_element("displayName")
                for another_item in that.display_name:
                    self.visit(another_item)
                self._write_end_element("displayName")

        if that.description is not None:
            if len(that.description) == 0:
                self._write_empty_element("description")
            else:
                self._write_start_element("description")
                for yet_another_item in that.description:
                    self.visit(yet_another_item)
                self._write_end_element("description")

        if that.semantic_id is not None:
            self._write_start_element("semanticId")
            self._write_reference_as_sequence(that.semantic_id)
            self._write_end_element("semanticId")

        if that.supplemental_semantic_ids is not None:
            if len(that.supplemental_semantic_ids) == 0:
                self._write_empty_element("supplementalSemanticIds")
            else:
                self._write_start_element("supplementalSemanticIds")
                for yet_yet_another_item in that.supplemental_semantic_ids:
                    self.visit(yet_yet_another_item)
                self._write_end_element("supplementalSemanticIds")

        if that.qualifiers is not None:
            if len(that.qualifiers) == 0:
                self._write_empty_element("qualifiers")
            else:
                self._write_start_element("qualifiers")
                for yet_yet_yet_another_item in that.qualifiers:
                    self.visit(yet_yet_yet_another_item)
                self._write_end_element("qualifiers")

        if that.embedded_data_specifications is not None:
            if len(that.embedded_data_specifications) == 0:
                self._write_empty_element("embeddedDataSpecifications")
            else:
                self._write_start_element("embeddedDataSpecifications")
                for yet_yet_yet_yet_another_item in that.embedded_data_specifications:
                    self.visit(yet_yet_yet_yet_another_item)
                self._write_end_element("embeddedDataSpecifications")

        if that.order_relevant is not None:
            self._write_bool_property("orderRelevant", that.order_relevant)

        if that.semantic_id_list_element is not None:
            self._write_start_element("semanticIdListElement")
            self._write_reference_as_sequence(that.semantic_id_list_element)
            self._write_end_element("semanticIdListElement")

        self._write_str_property(
            "typeValueListElement", that.type_value_list_element.value
        )

        if that.value_type_list_element is not None:
            self._write_str_property(
                "valueTypeListElement", that.value_type_list_element.value
            )

        if that.value is not None:
            if len(that.value) == 0:
                self._write_empty_element("value")
            else:
                self._write_start_element("value")
                for yet_yet_yet_yet_yet_another_item in that.value:
                    self.visit(yet_yet_yet_yet_yet_another_item)
                self._write_end_element("value")

    def visit_submodel_element_list(self, that: aas_types.SubmodelElementList) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("submodelElementList")
        self._write_submodel_element_list_as_sequence(that)
        self._write_end_element("submodelElementList")

    def _write_submodel_element_collection_as_sequence(
        self, that: aas_types.SubmodelElementCollection
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.extensions is not None:
            if len(that.extensions) == 0:
                self._write_empty_element("extensions")
            else:
                self._write_start_element("extensions")
                for an_item in that.extensions:
                    self.visit(an_item)
                self._write_end_element("extensions")

        if that.category is not None:
            self._write_str_property("category", that.category)

        if that.id_short is not None:
            self._write_str_property("idShort", that.id_short)

        if that.display_name is not None:
            if len(that.display_name) == 0:
                self._write_empty_element("displayName")
            else:
                self._write_start_element("displayName")
                for another_item in that.display_name:
                    self.visit(another_item)
                self._write_end_element("displayName")

        if that.description is not None:
            if len(that.description) == 0:
                self._write_empty_element("description")
            else:
                self._write_start_element("description")
                for yet_another_item in that.description:
                    self.visit(yet_another_item)
                self._write_end_element("description")

        if that.semantic_id is not None:
            self._write_start_element("semanticId")
            self._write_reference_as_sequence(that.semantic_id)
            self._write_end_element("semanticId")

        if that.supplemental_semantic_ids is not None:
            if len(that.supplemental_semantic_ids) == 0:
                self._write_empty_element("supplementalSemanticIds")
            else:
                self._write_start_element("supplementalSemanticIds")
                for yet_yet_another_item in that.supplemental_semantic_ids:
                    self.visit(yet_yet_another_item)
                self._write_end_element("supplementalSemanticIds")

        if that.qualifiers is not None:
            if len(that.qualifiers) == 0:
                self._write_empty_element("qualifiers")
            else:
                self._write_start_element("qualifiers")
                for yet_yet_yet_another_item in that.qualifiers:
                    self.visit(yet_yet_yet_another_item)
                self._write_end_element("qualifiers")

        if that.embedded_data_specifications is not None:
            if len(that.embedded_data_specifications) == 0:
                self._write_empty_element("embeddedDataSpecifications")
            else:
                self._write_start_element("embeddedDataSpecifications")
                for yet_yet_yet_yet_another_item in that.embedded_data_specifications:
                    self.visit(yet_yet_yet_yet_another_item)
                self._write_end_element("embeddedDataSpecifications")

        if that.value is not None:
            if len(that.value) == 0:
                self._write_empty_element("value")
            else:
                self._write_start_element("value")
                for yet_yet_yet_yet_yet_another_item in that.value:
                    self.visit(yet_yet_yet_yet_yet_another_item)
                self._write_end_element("value")

    def visit_submodel_element_collection(
        self, that: aas_types.SubmodelElementCollection
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        # We optimize for the case where all the optional properties are not set,
        # so that we can simply output an empty element.
        if (
            that.extensions is None
            and that.category is None
            and that.id_short is None
            and that.display_name is None
            and that.description is None
            and that.semantic_id is None
            and that.supplemental_semantic_ids is None
            and that.qualifiers is None
            and that.embedded_data_specifications is None
            and that.value is None
        ):
            self._write_empty_element("submodelElementCollection")
        else:
            self._write_start_element("submodelElementCollection")
            self._write_submodel_element_collection_as_sequence(that)
            self._write_end_element("submodelElementCollection")

    def _write_property_as_sequence(self, that: aas_types.Property) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.extensions is not None:
            if len(that.extensions) == 0:
                self._write_empty_element("extensions")
            else:
                self._write_start_element("extensions")
                for an_item in that.extensions:
                    self.visit(an_item)
                self._write_end_element("extensions")

        if that.category is not None:
            self._write_str_property("category", that.category)

        if that.id_short is not None:
            self._write_str_property("idShort", that.id_short)

        if that.display_name is not None:
            if len(that.display_name) == 0:
                self._write_empty_element("displayName")
            else:
                self._write_start_element("displayName")
                for another_item in that.display_name:
                    self.visit(another_item)
                self._write_end_element("displayName")

        if that.description is not None:
            if len(that.description) == 0:
                self._write_empty_element("description")
            else:
                self._write_start_element("description")
                for yet_another_item in that.description:
                    self.visit(yet_another_item)
                self._write_end_element("description")

        if that.semantic_id is not None:
            self._write_start_element("semanticId")
            self._write_reference_as_sequence(that.semantic_id)
            self._write_end_element("semanticId")

        if that.supplemental_semantic_ids is not None:
            if len(that.supplemental_semantic_ids) == 0:
                self._write_empty_element("supplementalSemanticIds")
            else:
                self._write_start_element("supplementalSemanticIds")
                for yet_yet_another_item in that.supplemental_semantic_ids:
                    self.visit(yet_yet_another_item)
                self._write_end_element("supplementalSemanticIds")

        if that.qualifiers is not None:
            if len(that.qualifiers) == 0:
                self._write_empty_element("qualifiers")
            else:
                self._write_start_element("qualifiers")
                for yet_yet_yet_another_item in that.qualifiers:
                    self.visit(yet_yet_yet_another_item)
                self._write_end_element("qualifiers")

        if that.embedded_data_specifications is not None:
            if len(that.embedded_data_specifications) == 0:
                self._write_empty_element("embeddedDataSpecifications")
            else:
                self._write_start_element("embeddedDataSpecifications")
                for yet_yet_yet_yet_another_item in that.embedded_data_specifications:
                    self.visit(yet_yet_yet_yet_another_item)
                self._write_end_element("embeddedDataSpecifications")

        self._write_str_property("valueType", that.value_type.value)

        if that.value is not None:
            self._write_str_property("value", that.value)

        if that.value_id is not None:
            self._write_start_element("valueId")
            self._write_reference_as_sequence(that.value_id)
            self._write_end_element("valueId")

    def visit_property(self, that: aas_types.Property) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("property")
        self._write_property_as_sequence(that)
        self._write_end_element("property")

    def _write_multi_language_property_as_sequence(
        self, that: aas_types.MultiLanguageProperty
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.extensions is not None:
            if len(that.extensions) == 0:
                self._write_empty_element("extensions")
            else:
                self._write_start_element("extensions")
                for an_item in that.extensions:
                    self.visit(an_item)
                self._write_end_element("extensions")

        if that.category is not None:
            self._write_str_property("category", that.category)

        if that.id_short is not None:
            self._write_str_property("idShort", that.id_short)

        if that.display_name is not None:
            if len(that.display_name) == 0:
                self._write_empty_element("displayName")
            else:
                self._write_start_element("displayName")
                for another_item in that.display_name:
                    self.visit(another_item)
                self._write_end_element("displayName")

        if that.description is not None:
            if len(that.description) == 0:
                self._write_empty_element("description")
            else:
                self._write_start_element("description")
                for yet_another_item in that.description:
                    self.visit(yet_another_item)
                self._write_end_element("description")

        if that.semantic_id is not None:
            self._write_start_element("semanticId")
            self._write_reference_as_sequence(that.semantic_id)
            self._write_end_element("semanticId")

        if that.supplemental_semantic_ids is not None:
            if len(that.supplemental_semantic_ids) == 0:
                self._write_empty_element("supplementalSemanticIds")
            else:
                self._write_start_element("supplementalSemanticIds")
                for yet_yet_another_item in that.supplemental_semantic_ids:
                    self.visit(yet_yet_another_item)
                self._write_end_element("supplementalSemanticIds")

        if that.qualifiers is not None:
            if len(that.qualifiers) == 0:
                self._write_empty_element("qualifiers")
            else:
                self._write_start_element("qualifiers")
                for yet_yet_yet_another_item in that.qualifiers:
                    self.visit(yet_yet_yet_another_item)
                self._write_end_element("qualifiers")

        if that.embedded_data_specifications is not None:
            if len(that.embedded_data_specifications) == 0:
                self._write_empty_element("embeddedDataSpecifications")
            else:
                self._write_start_element("embeddedDataSpecifications")
                for yet_yet_yet_yet_another_item in that.embedded_data_specifications:
                    self.visit(yet_yet_yet_yet_another_item)
                self._write_end_element("embeddedDataSpecifications")

        if that.value is not None:
            if len(that.value) == 0:
                self._write_empty_element("value")
            else:
                self._write_start_element("value")
                for yet_yet_yet_yet_yet_another_item in that.value:
                    self.visit(yet_yet_yet_yet_yet_another_item)
                self._write_end_element("value")

        if that.value_id is not None:
            self._write_start_element("valueId")
            self._write_reference_as_sequence(that.value_id)
            self._write_end_element("valueId")

    def visit_multi_language_property(
        self, that: aas_types.MultiLanguageProperty
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        # We optimize for the case where all the optional properties are not set,
        # so that we can simply output an empty element.
        if (
            that.extensions is None
            and that.category is None
            and that.id_short is None
            and that.display_name is None
            and that.description is None
            and that.semantic_id is None
            and that.supplemental_semantic_ids is None
            and that.qualifiers is None
            and that.embedded_data_specifications is None
            and that.value is None
            and that.value_id is None
        ):
            self._write_empty_element("multiLanguageProperty")
        else:
            self._write_start_element("multiLanguageProperty")
            self._write_multi_language_property_as_sequence(that)
            self._write_end_element("multiLanguageProperty")

    def _write_range_as_sequence(self, that: aas_types.Range) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.extensions is not None:
            if len(that.extensions) == 0:
                self._write_empty_element("extensions")
            else:
                self._write_start_element("extensions")
                for an_item in that.extensions:
                    self.visit(an_item)
                self._write_end_element("extensions")

        if that.category is not None:
            self._write_str_property("category", that.category)

        if that.id_short is not None:
            self._write_str_property("idShort", that.id_short)

        if that.display_name is not None:
            if len(that.display_name) == 0:
                self._write_empty_element("displayName")
            else:
                self._write_start_element("displayName")
                for another_item in that.display_name:
                    self.visit(another_item)
                self._write_end_element("displayName")

        if that.description is not None:
            if len(that.description) == 0:
                self._write_empty_element("description")
            else:
                self._write_start_element("description")
                for yet_another_item in that.description:
                    self.visit(yet_another_item)
                self._write_end_element("description")

        if that.semantic_id is not None:
            self._write_start_element("semanticId")
            self._write_reference_as_sequence(that.semantic_id)
            self._write_end_element("semanticId")

        if that.supplemental_semantic_ids is not None:
            if len(that.supplemental_semantic_ids) == 0:
                self._write_empty_element("supplementalSemanticIds")
            else:
                self._write_start_element("supplementalSemanticIds")
                for yet_yet_another_item in that.supplemental_semantic_ids:
                    self.visit(yet_yet_another_item)
                self._write_end_element("supplementalSemanticIds")

        if that.qualifiers is not None:
            if len(that.qualifiers) == 0:
                self._write_empty_element("qualifiers")
            else:
                self._write_start_element("qualifiers")
                for yet_yet_yet_another_item in that.qualifiers:
                    self.visit(yet_yet_yet_another_item)
                self._write_end_element("qualifiers")

        if that.embedded_data_specifications is not None:
            if len(that.embedded_data_specifications) == 0:
                self._write_empty_element("embeddedDataSpecifications")
            else:
                self._write_start_element("embeddedDataSpecifications")
                for yet_yet_yet_yet_another_item in that.embedded_data_specifications:
                    self.visit(yet_yet_yet_yet_another_item)
                self._write_end_element("embeddedDataSpecifications")

        self._write_str_property("valueType", that.value_type.value)

        if that.min is not None:
            self._write_str_property("min", that.min)

        if that.max is not None:
            self._write_str_property("max", that.max)

    def visit_range(self, that: aas_types.Range) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("range")
        self._write_range_as_sequence(that)
        self._write_end_element("range")

    def _write_reference_element_as_sequence(
        self, that: aas_types.ReferenceElement
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.extensions is not None:
            if len(that.extensions) == 0:
                self._write_empty_element("extensions")
            else:
                self._write_start_element("extensions")
                for an_item in that.extensions:
                    self.visit(an_item)
                self._write_end_element("extensions")

        if that.category is not None:
            self._write_str_property("category", that.category)

        if that.id_short is not None:
            self._write_str_property("idShort", that.id_short)

        if that.display_name is not None:
            if len(that.display_name) == 0:
                self._write_empty_element("displayName")
            else:
                self._write_start_element("displayName")
                for another_item in that.display_name:
                    self.visit(another_item)
                self._write_end_element("displayName")

        if that.description is not None:
            if len(that.description) == 0:
                self._write_empty_element("description")
            else:
                self._write_start_element("description")
                for yet_another_item in that.description:
                    self.visit(yet_another_item)
                self._write_end_element("description")

        if that.semantic_id is not None:
            self._write_start_element("semanticId")
            self._write_reference_as_sequence(that.semantic_id)
            self._write_end_element("semanticId")

        if that.supplemental_semantic_ids is not None:
            if len(that.supplemental_semantic_ids) == 0:
                self._write_empty_element("supplementalSemanticIds")
            else:
                self._write_start_element("supplementalSemanticIds")
                for yet_yet_another_item in that.supplemental_semantic_ids:
                    self.visit(yet_yet_another_item)
                self._write_end_element("supplementalSemanticIds")

        if that.qualifiers is not None:
            if len(that.qualifiers) == 0:
                self._write_empty_element("qualifiers")
            else:
                self._write_start_element("qualifiers")
                for yet_yet_yet_another_item in that.qualifiers:
                    self.visit(yet_yet_yet_another_item)
                self._write_end_element("qualifiers")

        if that.embedded_data_specifications is not None:
            if len(that.embedded_data_specifications) == 0:
                self._write_empty_element("embeddedDataSpecifications")
            else:
                self._write_start_element("embeddedDataSpecifications")
                for yet_yet_yet_yet_another_item in that.embedded_data_specifications:
                    self.visit(yet_yet_yet_yet_another_item)
                self._write_end_element("embeddedDataSpecifications")

        if that.value is not None:
            self._write_start_element("value")
            self._write_reference_as_sequence(that.value)
            self._write_end_element("value")

    def visit_reference_element(self, that: aas_types.ReferenceElement) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        # We optimize for the case where all the optional properties are not set,
        # so that we can simply output an empty element.
        if (
            that.extensions is None
            and that.category is None
            and that.id_short is None
            and that.display_name is None
            and that.description is None
            and that.semantic_id is None
            and that.supplemental_semantic_ids is None
            and that.qualifiers is None
            and that.embedded_data_specifications is None
            and that.value is None
        ):
            self._write_empty_element("referenceElement")
        else:
            self._write_start_element("referenceElement")
            self._write_reference_element_as_sequence(that)
            self._write_end_element("referenceElement")

    def _write_blob_as_sequence(self, that: aas_types.Blob) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.extensions is not None:
            if len(that.extensions) == 0:
                self._write_empty_element("extensions")
            else:
                self._write_start_element("extensions")
                for an_item in that.extensions:
                    self.visit(an_item)
                self._write_end_element("extensions")

        if that.category is not None:
            self._write_str_property("category", that.category)

        if that.id_short is not None:
            self._write_str_property("idShort", that.id_short)

        if that.display_name is not None:
            if len(that.display_name) == 0:
                self._write_empty_element("displayName")
            else:
                self._write_start_element("displayName")
                for another_item in that.display_name:
                    self.visit(another_item)
                self._write_end_element("displayName")

        if that.description is not None:
            if len(that.description) == 0:
                self._write_empty_element("description")
            else:
                self._write_start_element("description")
                for yet_another_item in that.description:
                    self.visit(yet_another_item)
                self._write_end_element("description")

        if that.semantic_id is not None:
            self._write_start_element("semanticId")
            self._write_reference_as_sequence(that.semantic_id)
            self._write_end_element("semanticId")

        if that.supplemental_semantic_ids is not None:
            if len(that.supplemental_semantic_ids) == 0:
                self._write_empty_element("supplementalSemanticIds")
            else:
                self._write_start_element("supplementalSemanticIds")
                for yet_yet_another_item in that.supplemental_semantic_ids:
                    self.visit(yet_yet_another_item)
                self._write_end_element("supplementalSemanticIds")

        if that.qualifiers is not None:
            if len(that.qualifiers) == 0:
                self._write_empty_element("qualifiers")
            else:
                self._write_start_element("qualifiers")
                for yet_yet_yet_another_item in that.qualifiers:
                    self.visit(yet_yet_yet_another_item)
                self._write_end_element("qualifiers")

        if that.embedded_data_specifications is not None:
            if len(that.embedded_data_specifications) == 0:
                self._write_empty_element("embeddedDataSpecifications")
            else:
                self._write_start_element("embeddedDataSpecifications")
                for yet_yet_yet_yet_another_item in that.embedded_data_specifications:
                    self.visit(yet_yet_yet_yet_another_item)
                self._write_end_element("embeddedDataSpecifications")

        if that.value is not None:
            self._write_bytes_property("value", that.value)

        self._write_str_property("contentType", that.content_type)

    def visit_blob(self, that: aas_types.Blob) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("blob")
        self._write_blob_as_sequence(that)
        self._write_end_element("blob")

    def _write_file_as_sequence(self, that: aas_types.File) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.extensions is not None:
            if len(that.extensions) == 0:
                self._write_empty_element("extensions")
            else:
                self._write_start_element("extensions")
                for an_item in that.extensions:
                    self.visit(an_item)
                self._write_end_element("extensions")

        if that.category is not None:
            self._write_str_property("category", that.category)

        if that.id_short is not None:
            self._write_str_property("idShort", that.id_short)

        if that.display_name is not None:
            if len(that.display_name) == 0:
                self._write_empty_element("displayName")
            else:
                self._write_start_element("displayName")
                for another_item in that.display_name:
                    self.visit(another_item)
                self._write_end_element("displayName")

        if that.description is not None:
            if len(that.description) == 0:
                self._write_empty_element("description")
            else:
                self._write_start_element("description")
                for yet_another_item in that.description:
                    self.visit(yet_another_item)
                self._write_end_element("description")

        if that.semantic_id is not None:
            self._write_start_element("semanticId")
            self._write_reference_as_sequence(that.semantic_id)
            self._write_end_element("semanticId")

        if that.supplemental_semantic_ids is not None:
            if len(that.supplemental_semantic_ids) == 0:
                self._write_empty_element("supplementalSemanticIds")
            else:
                self._write_start_element("supplementalSemanticIds")
                for yet_yet_another_item in that.supplemental_semantic_ids:
                    self.visit(yet_yet_another_item)
                self._write_end_element("supplementalSemanticIds")

        if that.qualifiers is not None:
            if len(that.qualifiers) == 0:
                self._write_empty_element("qualifiers")
            else:
                self._write_start_element("qualifiers")
                for yet_yet_yet_another_item in that.qualifiers:
                    self.visit(yet_yet_yet_another_item)
                self._write_end_element("qualifiers")

        if that.embedded_data_specifications is not None:
            if len(that.embedded_data_specifications) == 0:
                self._write_empty_element("embeddedDataSpecifications")
            else:
                self._write_start_element("embeddedDataSpecifications")
                for yet_yet_yet_yet_another_item in that.embedded_data_specifications:
                    self.visit(yet_yet_yet_yet_another_item)
                self._write_end_element("embeddedDataSpecifications")

        if that.value is not None:
            self._write_str_property("value", that.value)

        self._write_str_property("contentType", that.content_type)

    def visit_file(self, that: aas_types.File) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("file")
        self._write_file_as_sequence(that)
        self._write_end_element("file")

    def _write_annotated_relationship_element_as_sequence(
        self, that: aas_types.AnnotatedRelationshipElement
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.extensions is not None:
            if len(that.extensions) == 0:
                self._write_empty_element("extensions")
            else:
                self._write_start_element("extensions")
                for an_item in that.extensions:
                    self.visit(an_item)
                self._write_end_element("extensions")

        if that.category is not None:
            self._write_str_property("category", that.category)

        if that.id_short is not None:
            self._write_str_property("idShort", that.id_short)

        if that.display_name is not None:
            if len(that.display_name) == 0:
                self._write_empty_element("displayName")
            else:
                self._write_start_element("displayName")
                for another_item in that.display_name:
                    self.visit(another_item)
                self._write_end_element("displayName")

        if that.description is not None:
            if len(that.description) == 0:
                self._write_empty_element("description")
            else:
                self._write_start_element("description")
                for yet_another_item in that.description:
                    self.visit(yet_another_item)
                self._write_end_element("description")

        if that.semantic_id is not None:
            self._write_start_element("semanticId")
            self._write_reference_as_sequence(that.semantic_id)
            self._write_end_element("semanticId")

        if that.supplemental_semantic_ids is not None:
            if len(that.supplemental_semantic_ids) == 0:
                self._write_empty_element("supplementalSemanticIds")
            else:
                self._write_start_element("supplementalSemanticIds")
                for yet_yet_another_item in that.supplemental_semantic_ids:
                    self.visit(yet_yet_another_item)
                self._write_end_element("supplementalSemanticIds")

        if that.qualifiers is not None:
            if len(that.qualifiers) == 0:
                self._write_empty_element("qualifiers")
            else:
                self._write_start_element("qualifiers")
                for yet_yet_yet_another_item in that.qualifiers:
                    self.visit(yet_yet_yet_another_item)
                self._write_end_element("qualifiers")

        if that.embedded_data_specifications is not None:
            if len(that.embedded_data_specifications) == 0:
                self._write_empty_element("embeddedDataSpecifications")
            else:
                self._write_start_element("embeddedDataSpecifications")
                for yet_yet_yet_yet_another_item in that.embedded_data_specifications:
                    self.visit(yet_yet_yet_yet_another_item)
                self._write_end_element("embeddedDataSpecifications")

        self._write_start_element("first")
        self._write_reference_as_sequence(that.first)
        self._write_end_element("first")

        self._write_start_element("second")
        self._write_reference_as_sequence(that.second)
        self._write_end_element("second")

        if that.annotations is not None:
            if len(that.annotations) == 0:
                self._write_empty_element("annotations")
            else:
                self._write_start_element("annotations")
                for yet_yet_yet_yet_yet_another_item in that.annotations:
                    self.visit(yet_yet_yet_yet_yet_another_item)
                self._write_end_element("annotations")

    def visit_annotated_relationship_element(
        self, that: aas_types.AnnotatedRelationshipElement
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("annotatedRelationshipElement")
        self._write_annotated_relationship_element_as_sequence(that)
        self._write_end_element("annotatedRelationshipElement")

    def _write_entity_as_sequence(self, that: aas_types.Entity) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.extensions is not None:
            if len(that.extensions) == 0:
                self._write_empty_element("extensions")
            else:
                self._write_start_element("extensions")
                for an_item in that.extensions:
                    self.visit(an_item)
                self._write_end_element("extensions")

        if that.category is not None:
            self._write_str_property("category", that.category)

        if that.id_short is not None:
            self._write_str_property("idShort", that.id_short)

        if that.display_name is not None:
            if len(that.display_name) == 0:
                self._write_empty_element("displayName")
            else:
                self._write_start_element("displayName")
                for another_item in that.display_name:
                    self.visit(another_item)
                self._write_end_element("displayName")

        if that.description is not None:
            if len(that.description) == 0:
                self._write_empty_element("description")
            else:
                self._write_start_element("description")
                for yet_another_item in that.description:
                    self.visit(yet_another_item)
                self._write_end_element("description")

        if that.semantic_id is not None:
            self._write_start_element("semanticId")
            self._write_reference_as_sequence(that.semantic_id)
            self._write_end_element("semanticId")

        if that.supplemental_semantic_ids is not None:
            if len(that.supplemental_semantic_ids) == 0:
                self._write_empty_element("supplementalSemanticIds")
            else:
                self._write_start_element("supplementalSemanticIds")
                for yet_yet_another_item in that.supplemental_semantic_ids:
                    self.visit(yet_yet_another_item)
                self._write_end_element("supplementalSemanticIds")

        if that.qualifiers is not None:
            if len(that.qualifiers) == 0:
                self._write_empty_element("qualifiers")
            else:
                self._write_start_element("qualifiers")
                for yet_yet_yet_another_item in that.qualifiers:
                    self.visit(yet_yet_yet_another_item)
                self._write_end_element("qualifiers")

        if that.embedded_data_specifications is not None:
            if len(that.embedded_data_specifications) == 0:
                self._write_empty_element("embeddedDataSpecifications")
            else:
                self._write_start_element("embeddedDataSpecifications")
                for yet_yet_yet_yet_another_item in that.embedded_data_specifications:
                    self.visit(yet_yet_yet_yet_another_item)
                self._write_end_element("embeddedDataSpecifications")

        if that.statements is not None:
            if len(that.statements) == 0:
                self._write_empty_element("statements")
            else:
                self._write_start_element("statements")
                for yet_yet_yet_yet_yet_another_item in that.statements:
                    self.visit(yet_yet_yet_yet_yet_another_item)
                self._write_end_element("statements")

        self._write_str_property("entityType", that.entity_type.value)

        if that.global_asset_id is not None:
            self._write_str_property("globalAssetId", that.global_asset_id)

        if that.specific_asset_ids is not None:
            if len(that.specific_asset_ids) == 0:
                self._write_empty_element("specificAssetIds")
            else:
                self._write_start_element("specificAssetIds")
                for yet_yet_yet_yet_yet_yet_another_item in that.specific_asset_ids:
                    self.visit(yet_yet_yet_yet_yet_yet_another_item)
                self._write_end_element("specificAssetIds")

    def visit_entity(self, that: aas_types.Entity) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("entity")
        self._write_entity_as_sequence(that)
        self._write_end_element("entity")

    def _write_event_payload_as_sequence(self, that: aas_types.EventPayload) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        self._write_start_element("source")
        self._write_reference_as_sequence(that.source)
        self._write_end_element("source")

        if that.source_semantic_id is not None:
            self._write_start_element("sourceSemanticId")
            self._write_reference_as_sequence(that.source_semantic_id)
            self._write_end_element("sourceSemanticId")

        self._write_start_element("observableReference")
        self._write_reference_as_sequence(that.observable_reference)
        self._write_end_element("observableReference")

        if that.observable_semantic_id is not None:
            self._write_start_element("observableSemanticId")
            self._write_reference_as_sequence(that.observable_semantic_id)
            self._write_end_element("observableSemanticId")

        if that.topic is not None:
            self._write_str_property("topic", that.topic)

        if that.subject_id is not None:
            self._write_start_element("subjectId")
            self._write_reference_as_sequence(that.subject_id)
            self._write_end_element("subjectId")

        self._write_str_property("timeStamp", that.time_stamp)

        if that.payload is not None:
            self._write_bytes_property("payload", that.payload)

    def visit_event_payload(self, that: aas_types.EventPayload) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("eventPayload")
        self._write_event_payload_as_sequence(that)
        self._write_end_element("eventPayload")

    def _write_basic_event_element_as_sequence(
        self, that: aas_types.BasicEventElement
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.extensions is not None:
            if len(that.extensions) == 0:
                self._write_empty_element("extensions")
            else:
                self._write_start_element("extensions")
                for an_item in that.extensions:
                    self.visit(an_item)
                self._write_end_element("extensions")

        if that.category is not None:
            self._write_str_property("category", that.category)

        if that.id_short is not None:
            self._write_str_property("idShort", that.id_short)

        if that.display_name is not None:
            if len(that.display_name) == 0:
                self._write_empty_element("displayName")
            else:
                self._write_start_element("displayName")
                for another_item in that.display_name:
                    self.visit(another_item)
                self._write_end_element("displayName")

        if that.description is not None:
            if len(that.description) == 0:
                self._write_empty_element("description")
            else:
                self._write_start_element("description")
                for yet_another_item in that.description:
                    self.visit(yet_another_item)
                self._write_end_element("description")

        if that.semantic_id is not None:
            self._write_start_element("semanticId")
            self._write_reference_as_sequence(that.semantic_id)
            self._write_end_element("semanticId")

        if that.supplemental_semantic_ids is not None:
            if len(that.supplemental_semantic_ids) == 0:
                self._write_empty_element("supplementalSemanticIds")
            else:
                self._write_start_element("supplementalSemanticIds")
                for yet_yet_another_item in that.supplemental_semantic_ids:
                    self.visit(yet_yet_another_item)
                self._write_end_element("supplementalSemanticIds")

        if that.qualifiers is not None:
            if len(that.qualifiers) == 0:
                self._write_empty_element("qualifiers")
            else:
                self._write_start_element("qualifiers")
                for yet_yet_yet_another_item in that.qualifiers:
                    self.visit(yet_yet_yet_another_item)
                self._write_end_element("qualifiers")

        if that.embedded_data_specifications is not None:
            if len(that.embedded_data_specifications) == 0:
                self._write_empty_element("embeddedDataSpecifications")
            else:
                self._write_start_element("embeddedDataSpecifications")
                for yet_yet_yet_yet_another_item in that.embedded_data_specifications:
                    self.visit(yet_yet_yet_yet_another_item)
                self._write_end_element("embeddedDataSpecifications")

        self._write_start_element("observed")
        self._write_reference_as_sequence(that.observed)
        self._write_end_element("observed")

        self._write_str_property("direction", that.direction.value)

        self._write_str_property("state", that.state.value)

        if that.message_topic is not None:
            self._write_str_property("messageTopic", that.message_topic)

        if that.message_broker is not None:
            self._write_start_element("messageBroker")
            self._write_reference_as_sequence(that.message_broker)
            self._write_end_element("messageBroker")

        if that.last_update is not None:
            self._write_str_property("lastUpdate", that.last_update)

        if that.min_interval is not None:
            self._write_str_property("minInterval", that.min_interval)

        if that.max_interval is not None:
            self._write_str_property("maxInterval", that.max_interval)

    def visit_basic_event_element(self, that: aas_types.BasicEventElement) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("basicEventElement")
        self._write_basic_event_element_as_sequence(that)
        self._write_end_element("basicEventElement")

    def _write_operation_as_sequence(self, that: aas_types.Operation) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.extensions is not None:
            if len(that.extensions) == 0:
                self._write_empty_element("extensions")
            else:
                self._write_start_element("extensions")
                for an_item in that.extensions:
                    self.visit(an_item)
                self._write_end_element("extensions")

        if that.category is not None:
            self._write_str_property("category", that.category)

        if that.id_short is not None:
            self._write_str_property("idShort", that.id_short)

        if that.display_name is not None:
            if len(that.display_name) == 0:
                self._write_empty_element("displayName")
            else:
                self._write_start_element("displayName")
                for another_item in that.display_name:
                    self.visit(another_item)
                self._write_end_element("displayName")

        if that.description is not None:
            if len(that.description) == 0:
                self._write_empty_element("description")
            else:
                self._write_start_element("description")
                for yet_another_item in that.description:
                    self.visit(yet_another_item)
                self._write_end_element("description")

        if that.semantic_id is not None:
            self._write_start_element("semanticId")
            self._write_reference_as_sequence(that.semantic_id)
            self._write_end_element("semanticId")

        if that.supplemental_semantic_ids is not None:
            if len(that.supplemental_semantic_ids) == 0:
                self._write_empty_element("supplementalSemanticIds")
            else:
                self._write_start_element("supplementalSemanticIds")
                for yet_yet_another_item in that.supplemental_semantic_ids:
                    self.visit(yet_yet_another_item)
                self._write_end_element("supplementalSemanticIds")

        if that.qualifiers is not None:
            if len(that.qualifiers) == 0:
                self._write_empty_element("qualifiers")
            else:
                self._write_start_element("qualifiers")
                for yet_yet_yet_another_item in that.qualifiers:
                    self.visit(yet_yet_yet_another_item)
                self._write_end_element("qualifiers")

        if that.embedded_data_specifications is not None:
            if len(that.embedded_data_specifications) == 0:
                self._write_empty_element("embeddedDataSpecifications")
            else:
                self._write_start_element("embeddedDataSpecifications")
                for yet_yet_yet_yet_another_item in that.embedded_data_specifications:
                    self.visit(yet_yet_yet_yet_another_item)
                self._write_end_element("embeddedDataSpecifications")

        if that.input_variables is not None:
            if len(that.input_variables) == 0:
                self._write_empty_element("inputVariables")
            else:
                self._write_start_element("inputVariables")
                for yet_yet_yet_yet_yet_another_item in that.input_variables:
                    self.visit(yet_yet_yet_yet_yet_another_item)
                self._write_end_element("inputVariables")

        if that.output_variables is not None:
            if len(that.output_variables) == 0:
                self._write_empty_element("outputVariables")
            else:
                self._write_start_element("outputVariables")
                for yet_yet_yet_yet_yet_yet_another_item in that.output_variables:
                    self.visit(yet_yet_yet_yet_yet_yet_another_item)
                self._write_end_element("outputVariables")

        if that.inoutput_variables is not None:
            if len(that.inoutput_variables) == 0:
                self._write_empty_element("inoutputVariables")
            else:
                self._write_start_element("inoutputVariables")
                for yet_yet_yet_yet_yet_yet_yet_another_item in that.inoutput_variables:
                    self.visit(yet_yet_yet_yet_yet_yet_yet_another_item)
                self._write_end_element("inoutputVariables")

    def visit_operation(self, that: aas_types.Operation) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        # We optimize for the case where all the optional properties are not set,
        # so that we can simply output an empty element.
        if (
            that.extensions is None
            and that.category is None
            and that.id_short is None
            and that.display_name is None
            and that.description is None
            and that.semantic_id is None
            and that.supplemental_semantic_ids is None
            and that.qualifiers is None
            and that.embedded_data_specifications is None
            and that.input_variables is None
            and that.output_variables is None
            and that.inoutput_variables is None
        ):
            self._write_empty_element("operation")
        else:
            self._write_start_element("operation")
            self._write_operation_as_sequence(that)
            self._write_end_element("operation")

    def _write_operation_variable_as_sequence(
        self, that: aas_types.OperationVariable
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        self._write_start_element("value")
        self.visit(that.value)
        self._write_end_element("value")

    def visit_operation_variable(self, that: aas_types.OperationVariable) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("operationVariable")
        self._write_operation_variable_as_sequence(that)
        self._write_end_element("operationVariable")

    def _write_capability_as_sequence(self, that: aas_types.Capability) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.extensions is not None:
            if len(that.extensions) == 0:
                self._write_empty_element("extensions")
            else:
                self._write_start_element("extensions")
                for an_item in that.extensions:
                    self.visit(an_item)
                self._write_end_element("extensions")

        if that.category is not None:
            self._write_str_property("category", that.category)

        if that.id_short is not None:
            self._write_str_property("idShort", that.id_short)

        if that.display_name is not None:
            if len(that.display_name) == 0:
                self._write_empty_element("displayName")
            else:
                self._write_start_element("displayName")
                for another_item in that.display_name:
                    self.visit(another_item)
                self._write_end_element("displayName")

        if that.description is not None:
            if len(that.description) == 0:
                self._write_empty_element("description")
            else:
                self._write_start_element("description")
                for yet_another_item in that.description:
                    self.visit(yet_another_item)
                self._write_end_element("description")

        if that.semantic_id is not None:
            self._write_start_element("semanticId")
            self._write_reference_as_sequence(that.semantic_id)
            self._write_end_element("semanticId")

        if that.supplemental_semantic_ids is not None:
            if len(that.supplemental_semantic_ids) == 0:
                self._write_empty_element("supplementalSemanticIds")
            else:
                self._write_start_element("supplementalSemanticIds")
                for yet_yet_another_item in that.supplemental_semantic_ids:
                    self.visit(yet_yet_another_item)
                self._write_end_element("supplementalSemanticIds")

        if that.qualifiers is not None:
            if len(that.qualifiers) == 0:
                self._write_empty_element("qualifiers")
            else:
                self._write_start_element("qualifiers")
                for yet_yet_yet_another_item in that.qualifiers:
                    self.visit(yet_yet_yet_another_item)
                self._write_end_element("qualifiers")

        if that.embedded_data_specifications is not None:
            if len(that.embedded_data_specifications) == 0:
                self._write_empty_element("embeddedDataSpecifications")
            else:
                self._write_start_element("embeddedDataSpecifications")
                for yet_yet_yet_yet_another_item in that.embedded_data_specifications:
                    self.visit(yet_yet_yet_yet_another_item)
                self._write_end_element("embeddedDataSpecifications")

    def visit_capability(self, that: aas_types.Capability) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        # We optimize for the case where all the optional properties are not set,
        # so that we can simply output an empty element.
        if (
            that.extensions is None
            and that.category is None
            and that.id_short is None
            and that.display_name is None
            and that.description is None
            and that.semantic_id is None
            and that.supplemental_semantic_ids is None
            and that.qualifiers is None
            and that.embedded_data_specifications is None
        ):
            self._write_empty_element("capability")
        else:
            self._write_start_element("capability")
            self._write_capability_as_sequence(that)
            self._write_end_element("capability")

    def _write_concept_description_as_sequence(
        self, that: aas_types.ConceptDescription
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.extensions is not None:
            if len(that.extensions) == 0:
                self._write_empty_element("extensions")
            else:
                self._write_start_element("extensions")
                for an_item in that.extensions:
                    self.visit(an_item)
                self._write_end_element("extensions")

        if that.category is not None:
            self._write_str_property("category", that.category)

        if that.id_short is not None:
            self._write_str_property("idShort", that.id_short)

        if that.display_name is not None:
            if len(that.display_name) == 0:
                self._write_empty_element("displayName")
            else:
                self._write_start_element("displayName")
                for another_item in that.display_name:
                    self.visit(another_item)
                self._write_end_element("displayName")

        if that.description is not None:
            if len(that.description) == 0:
                self._write_empty_element("description")
            else:
                self._write_start_element("description")
                for yet_another_item in that.description:
                    self.visit(yet_another_item)
                self._write_end_element("description")

        if that.administration is not None:
            the_administration = that.administration
            # We optimize for the case where all the optional properties are not set,
            # so that we can simply output an empty element.
            if (
                the_administration.embedded_data_specifications is None
                and the_administration.version is None
                and the_administration.revision is None
                and the_administration.creator is None
                and the_administration.template_id is None
            ):
                self._write_empty_element("administration")
            else:
                self._write_start_element("administration")
                self._write_administrative_information_as_sequence(the_administration)
                self._write_end_element("administration")

        self._write_str_property("id", that.id)

        if that.embedded_data_specifications is not None:
            if len(that.embedded_data_specifications) == 0:
                self._write_empty_element("embeddedDataSpecifications")
            else:
                self._write_start_element("embeddedDataSpecifications")
                for yet_yet_another_item in that.embedded_data_specifications:
                    self.visit(yet_yet_another_item)
                self._write_end_element("embeddedDataSpecifications")

        if that.is_case_of is not None:
            if len(that.is_case_of) == 0:
                self._write_empty_element("isCaseOf")
            else:
                self._write_start_element("isCaseOf")
                for yet_yet_yet_another_item in that.is_case_of:
                    self.visit(yet_yet_yet_another_item)
                self._write_end_element("isCaseOf")

    def visit_concept_description(self, that: aas_types.ConceptDescription) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("conceptDescription")
        self._write_concept_description_as_sequence(that)
        self._write_end_element("conceptDescription")

    def _write_reference_as_sequence(self, that: aas_types.Reference) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        self._write_str_property("type", that.type.value)

        if that.referred_semantic_id is not None:
            self._write_start_element("referredSemanticId")
            self._write_reference_as_sequence(that.referred_semantic_id)
            self._write_end_element("referredSemanticId")

        if len(that.keys) == 0:
            self._write_empty_element("keys")
        else:
            self._write_start_element("keys")
            for an_item in that.keys:
                self.visit(an_item)
            self._write_end_element("keys")

    def visit_reference(self, that: aas_types.Reference) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("reference")
        self._write_reference_as_sequence(that)
        self._write_end_element("reference")

    def _write_key_as_sequence(self, that: aas_types.Key) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        self._write_str_property("type", that.type.value)

        self._write_str_property("value", that.value)

    def visit_key(self, that: aas_types.Key) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("key")
        self._write_key_as_sequence(that)
        self._write_end_element("key")

    def _write_lang_string_name_type_as_sequence(
        self, that: aas_types.LangStringNameType
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        self._write_str_property("language", that.language)

        self._write_str_property("text", that.text)

    def visit_lang_string_name_type(self, that: aas_types.LangStringNameType) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("langStringNameType")
        self._write_lang_string_name_type_as_sequence(that)
        self._write_end_element("langStringNameType")

    def _write_lang_string_text_type_as_sequence(
        self, that: aas_types.LangStringTextType
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        self._write_str_property("language", that.language)

        self._write_str_property("text", that.text)

    def visit_lang_string_text_type(self, that: aas_types.LangStringTextType) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("langStringTextType")
        self._write_lang_string_text_type_as_sequence(that)
        self._write_end_element("langStringTextType")

    def _write_environment_as_sequence(self, that: aas_types.Environment) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if that.asset_administration_shells is not None:
            if len(that.asset_administration_shells) == 0:
                self._write_empty_element("assetAdministrationShells")
            else:
                self._write_start_element("assetAdministrationShells")
                for an_item in that.asset_administration_shells:
                    self.visit(an_item)
                self._write_end_element("assetAdministrationShells")

        if that.submodels is not None:
            if len(that.submodels) == 0:
                self._write_empty_element("submodels")
            else:
                self._write_start_element("submodels")
                for another_item in that.submodels:
                    self.visit(another_item)
                self._write_end_element("submodels")

        if that.concept_descriptions is not None:
            if len(that.concept_descriptions) == 0:
                self._write_empty_element("conceptDescriptions")
            else:
                self._write_start_element("conceptDescriptions")
                for yet_another_item in that.concept_descriptions:
                    self.visit(yet_another_item)
                self._write_end_element("conceptDescriptions")

    def visit_environment(self, that: aas_types.Environment) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        # We optimize for the case where all the optional properties are not set,
        # so that we can simply output an empty element.
        if (
            that.asset_administration_shells is None
            and that.submodels is None
            and that.concept_descriptions is None
        ):
            self._write_empty_element("environment")
        else:
            self._write_start_element("environment")
            self._write_environment_as_sequence(that)
            self._write_end_element("environment")

    def _write_embedded_data_specification_as_sequence(
        self, that: aas_types.EmbeddedDataSpecification
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        self._write_start_element("dataSpecification")
        self._write_reference_as_sequence(that.data_specification)
        self._write_end_element("dataSpecification")

        self._write_start_element("dataSpecificationContent")
        self.visit(that.data_specification_content)
        self._write_end_element("dataSpecificationContent")

    def visit_embedded_data_specification(
        self, that: aas_types.EmbeddedDataSpecification
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("embeddedDataSpecification")
        self._write_embedded_data_specification_as_sequence(that)
        self._write_end_element("embeddedDataSpecification")

    def _write_level_type_as_sequence(self, that: aas_types.LevelType) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        self._write_bool_property("min", that.min)

        self._write_bool_property("nom", that.nom)

        self._write_bool_property("typ", that.typ)

        self._write_bool_property("max", that.max)

    def visit_level_type(self, that: aas_types.LevelType) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("levelType")
        self._write_level_type_as_sequence(that)
        self._write_end_element("levelType")

    def _write_value_reference_pair_as_sequence(
        self, that: aas_types.ValueReferencePair
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        self._write_str_property("value", that.value)

        self._write_start_element("valueId")
        self._write_reference_as_sequence(that.value_id)
        self._write_end_element("valueId")

    def visit_value_reference_pair(self, that: aas_types.ValueReferencePair) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("valueReferencePair")
        self._write_value_reference_pair_as_sequence(that)
        self._write_end_element("valueReferencePair")

    def _write_value_list_as_sequence(self, that: aas_types.ValueList) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if len(that.value_reference_pairs) == 0:
            self._write_empty_element("valueReferencePairs")
        else:
            self._write_start_element("valueReferencePairs")
            for an_item in that.value_reference_pairs:
                self.visit(an_item)
            self._write_end_element("valueReferencePairs")

    def visit_value_list(self, that: aas_types.ValueList) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("valueList")
        self._write_value_list_as_sequence(that)
        self._write_end_element("valueList")

    def _write_lang_string_preferred_name_type_iec_61360_as_sequence(
        self, that: aas_types.LangStringPreferredNameTypeIEC61360
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        self._write_str_property("language", that.language)

        self._write_str_property("text", that.text)

    def visit_lang_string_preferred_name_type_iec_61360(
        self, that: aas_types.LangStringPreferredNameTypeIEC61360
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("langStringPreferredNameTypeIec61360")
        self._write_lang_string_preferred_name_type_iec_61360_as_sequence(that)
        self._write_end_element("langStringPreferredNameTypeIec61360")

    def _write_lang_string_short_name_type_iec_61360_as_sequence(
        self, that: aas_types.LangStringShortNameTypeIEC61360
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        self._write_str_property("language", that.language)

        self._write_str_property("text", that.text)

    def visit_lang_string_short_name_type_iec_61360(
        self, that: aas_types.LangStringShortNameTypeIEC61360
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("langStringShortNameTypeIec61360")
        self._write_lang_string_short_name_type_iec_61360_as_sequence(that)
        self._write_end_element("langStringShortNameTypeIec61360")

    def _write_lang_string_definition_type_iec_61360_as_sequence(
        self, that: aas_types.LangStringDefinitionTypeIEC61360
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        self._write_str_property("language", that.language)

        self._write_str_property("text", that.text)

    def visit_lang_string_definition_type_iec_61360(
        self, that: aas_types.LangStringDefinitionTypeIEC61360
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("langStringDefinitionTypeIec61360")
        self._write_lang_string_definition_type_iec_61360_as_sequence(that)
        self._write_end_element("langStringDefinitionTypeIec61360")

    def _write_data_specification_iec_61360_as_sequence(
        self, that: aas_types.DataSpecificationIEC61360
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as a sequence of
        XML elements.

        Each element in the sequence corresponds to a property. If no properties
        are set, nothing is written to the :py:attr:`~stream`.

        :param that: instance to be serialized
        """
        if len(that.preferred_name) == 0:
            self._write_empty_element("preferredName")
        else:
            self._write_start_element("preferredName")
            for an_item in that.preferred_name:
                self.visit(an_item)
            self._write_end_element("preferredName")

        if that.short_name is not None:
            if len(that.short_name) == 0:
                self._write_empty_element("shortName")
            else:
                self._write_start_element("shortName")
                for another_item in that.short_name:
                    self.visit(another_item)
                self._write_end_element("shortName")

        if that.unit is not None:
            self._write_str_property("unit", that.unit)

        if that.unit_id is not None:
            self._write_start_element("unitId")
            self._write_reference_as_sequence(that.unit_id)
            self._write_end_element("unitId")

        if that.source_of_definition is not None:
            self._write_str_property("sourceOfDefinition", that.source_of_definition)

        if that.symbol is not None:
            self._write_str_property("symbol", that.symbol)

        if that.data_type is not None:
            self._write_str_property("dataType", that.data_type.value)

        if that.definition is not None:
            if len(that.definition) == 0:
                self._write_empty_element("definition")
            else:
                self._write_start_element("definition")
                for yet_another_item in that.definition:
                    self.visit(yet_another_item)
                self._write_end_element("definition")

        if that.value_format is not None:
            self._write_str_property("valueFormat", that.value_format)

        if that.value_list is not None:
            self._write_start_element("valueList")
            self._write_value_list_as_sequence(that.value_list)
            self._write_end_element("valueList")

        if that.value is not None:
            self._write_str_property("value", that.value)

        if that.level_type is not None:
            self._write_start_element("levelType")
            self._write_level_type_as_sequence(that.level_type)
            self._write_end_element("levelType")

    def visit_data_specification_iec_61360(
        self, that: aas_types.DataSpecificationIEC61360
    ) -> None:
        """
        Serialize :paramref:`that` to :py:attr:`~stream` as an XML element.

        The enclosing XML element designates the class of the instance, where its
        children correspond to the properties of the instance.

        :param that: instance to be serialized
        """
        self._write_start_element("dataSpecificationIec61360")
        self._write_data_specification_iec_61360_as_sequence(that)
        self._write_end_element("dataSpecificationIec61360")


def write(instance: aas_types.Class, stream: TextIO) -> None:
    """
    Write the XML representation of :paramref:`instance` to :paramref:`stream`.

    Example usage:

    .. code-block::

        import pathlib

        import aas_core3.types as aas_types
        import aas_core3.xmlization as aas_xmlization

        instance = Extension(
           ... # some constructor arguments
        )

        pth = pathlib.Path(...)
        with pth.open("wt") as fid:
            aas_xmlization.write(instance, fid)

    :param instance: to be serialized
    :param stream: to write to
    """
    serializer = _Serializer(stream)
    serializer.visit(instance)


def to_str(that: aas_types.Class) -> str:
    """
    Serialize :paramref:`that` to an XML-encoded text.

    :param that: instance to be serialized
    :return: :paramref:`that` serialized to XML serialized to text
    """
    writer = io.StringIO()
    write(that, writer)
    return writer.getvalue()


# endregion
