r"""
    Parse the contents of the string ``s`` as an XML properties document and
    return a `dict` of the key-value pairs.

    Beyond basic XML well-formedness, `loads_xml` only checks that the root
    element is named "``properties``" and that all of its ``<entry>`` children
    have ``key`` attributes.  No further validation is performed; if any
    ``<entry>``\ s happen to contain nested tags, the behavior is undefined.

    By default, the key-value pairs extracted from ``s`` are combined into a
    `dict` with later occurrences of a key overriding previous occurrences of
    the same key.  To change this behavior, pass a callable as the
    ``object_pairs_hook`` argument; it will be called with one argument, a
    generator of ``(key, value)`` pairs representing the key-value entries in
    ``s`` (including duplicates) in order of occurrence.  `loads_xml` will then
    return the value returned by ``object_pairs_hook``.

    .. note::

        This uses `xml.etree.ElementTree` for parsing, which does not have
        decent support for |unicode|_ input in Python 2.  Strings containing
        non-ASCII characters need to be encoded as bytes in Python 2 (Use
        either UTF-8 or UTF-16 if the XML document does not contain an encoding
        declaration), while Python 3 accepts both binary and text input.

    :param string s: the string from which to read the XML properties document
    :param callable object_pairs_hook: class or function for combining the
        key-value pairs
    :rtype: `dict` or the return value of ``object_pairs_hook``
    :raises ValueError: if the root of the XML tree is not a ``<properties>``
        tag or an ``<entry>`` element is missing a ``key`` attribute

def loads_xml(s, object_pairs_hook=dict):
    r"""
    Parse the contents of the string ``s`` as an XML properties document and
    return a `dict` of the key-value pairs.

    Beyond basic XML well-formedness, `loads_xml` only checks that the root
    element is named "``properties``" and that all of its ``<entry>`` children
    have ``key`` attributes.  No further validation is performed; if any
    ``<entry>``\ s happen to contain nested tags, the behavior is undefined.

    By default, the key-value pairs extracted from ``s`` are combined into a
    `dict` with later occurrences of a key overriding previous occurrences of
    the same key.  To change this behavior, pass a callable as the
    ``object_pairs_hook`` argument; it will be called with one argument, a
    generator of ``(key, value)`` pairs representing the key-value entries in
    ``s`` (including duplicates) in order of occurrence.  `loads_xml` will then
    return the value returned by ``object_pairs_hook``.

    .. note::

        This uses `xml.etree.ElementTree` for parsing, which does not have
        decent support for |unicode|_ input in Python 2.  Strings containing
        non-ASCII characters need to be encoded as bytes in Python 2 (Use
        either UTF-8 or UTF-16 if the XML document does not contain an encoding
        declaration), while Python 3 accepts both binary and text input.

    :param string s: the string from which to read the XML properties document
    :param callable object_pairs_hook: class or function for combining the
        key-value pairs
    :rtype: `dict` or the return value of ``object_pairs_hook``
    :raises ValueError: if the root of the XML tree is not a ``<properties>``
        tag or an ``<entry>`` element is missing a ``key`` attribute
    """
    elem = ET.fromstring(s)
    return object_pairs_hook(_fromXML(elem))