# Path: flattentool/exceptions.py
# class DataErrorWarning(UserWarning):
#     """
#     A warnings that indicates an error in the data, rather than the schema.
# 
#     """
# 
#     pass
# 
# Path: flattentool/sort_xml.py
# class XMLSchemaWalker(object):
#     """
#     Class for traversing one or more XML schemas.
# 
#     Based on the Schema2Doc class in https://github.com/IATI/IATI-Standard-SSOT/blob/version-2.02/gen.py
#     """
# 
#     def __init__(self, schemas):
#         """
#         schema -- the filename of the schema to use, e.g.
#                   'iati-activities-schema.xsd'
#         """
#         self.trees = [ET.parse(schema) for schema in schemas]
# 
#     def get_schema_element(self, tag_name, name_attribute):
#         """
#         Return the specified element from the schema.
# 
#         tag_name -- the name of the tag in the schema, e.g. 'complexType'
#         name_attribute -- the value of the 'name' attribute in the schema, ie.
#                           the name of the element/type etc. being described,
#                           e.g. iati-activities
#         """
#         for tree in self.trees:
#             schema_element = tree.find(
#                 "xsd:{0}[@name='{1}']".format(tag_name, name_attribute),
#                 namespaces=namespaces,
#             )
#             if schema_element is not None:
#                 return schema_element
#         return schema_element
# 
#     def element_loop(self, element, path):
#         """
#         Return information about the children of the supplied element.
#         """
#         a = element.attrib
#         type_elements = []
#         if "type" in a:
#             complexType = self.get_schema_element("complexType", a["type"])
#             if complexType is not None:
#                 type_elements = complexType.findall(
#                     "xsd:choice/xsd:element", namespaces=namespaces
#                 ) + complexType.findall(
#                     "xsd:sequence/xsd:element", namespaces=namespaces
#                 )
# 
#         children = (
#             element.findall(
#                 "xsd:complexType/xsd:choice/xsd:element", namespaces=namespaces
#             )
#             + element.findall(
#                 "xsd:complexType/xsd:sequence/xsd:element", namespaces=namespaces
#             )
#             + element.findall(
#                 "xsd:complexType/xsd:all/xsd:element", namespaces=namespaces
#             )
#             + type_elements
#         )
#         child_tuples = []
#         for child in children:
#             a = child.attrib
#             if "name" in a:
#                 child_tuples.append(
#                     (a["name"], child, None, a.get("minOccurs"), a.get("maxOccurs"))
#                 )
#             else:
#                 child_tuples.append(
#                     (a["ref"], None, child, a.get("minOccurs"), a.get("maxOccurs"))
#                 )
#         return child_tuples
# 
#     def create_schema_dict(self, parent_name, parent_element=None):
#         """
#         Create a nested OrderedDict representing the structure (and order!) of
#         elements in the provided schema.
#         """
#         if parent_element is None:
#             parent_element = self.get_schema_element("element", parent_name)
#         if parent_element is None:
#             return {}
# 
#         return OrderedDict(
#             [
#                 (name, self.create_schema_dict(name, element))
#                 for name, element, _, _, _ in self.element_loop(parent_element, "")
#             ]
#         )
# 
# def sort_element(element, schema_subdict):
#     """
#     Sort the given element's children according to the order of schema_subdict.
#     """
#     children = list(element)
#     for child in children:
#         element.remove(child)
#     keys = list(schema_subdict.keys())
# 
#     def index_key(x):
#         if x.tag in keys:
#             return keys.index(x.tag)
#         else:
#             return len(keys) + 1
# 
#     for child in sorted(children, key=index_key):
#         element.append(child)
#         sort_element(child, schema_subdict.get(child.tag, {}))


from collections import OrderedDict
from warnings import warn
from flattentool.exceptions import DataErrorWarning
from flattentool.sort_xml import XMLSchemaWalker, sort_element
    import lxml.etree as ET
    import xml.etree.ElementTree as ET
        warn(str(e), DataErrorWarning)
        return

    if USING_LXML:
        data = sort_attributes(data)

    for k, v in data.items():
        if type(v) == list:
            for item in v:
                child_to_xml(el, k, item, nsmap=nsmap)
        else:
            child_to_xml(el, k, v, toplevel=toplevel, nsmap=nsmap)
    return el


def toxml(
    data,
    xml_root_tag,
    xml_schemas=None,
    root_list_path="iati-activity",
    xml_comment=None,
):
    nsmap = {
        # This is "bound by definition" - see https://www.w3.org/XML/1998/namespace
        "xml": "http://www.w3.org/XML/1998/namespace"
    }
    root = dict_to_xml(data, xml_root_tag, nsmap=nsmap)
    if xml_schemas is not None:
        schema_dict = XMLSchemaWalker(xml_schemas).create_schema_dict(root_list_path)
        for element in root:

# Path: flattentool/exceptions.py
# class DataErrorWarning(UserWarning):
#     """
#     A warnings that indicates an error in the data, rather than the schema.
# 
#     """
# 
#     pass
# 
# Path: flattentool/sort_xml.py
# class XMLSchemaWalker(object):
#     """
#     Class for traversing one or more XML schemas.
# 
#     Based on the Schema2Doc class in https://github.com/IATI/IATI-Standard-SSOT/blob/version-2.02/gen.py
#     """
# 
#     def __init__(self, schemas):
#         """
#         schema -- the filename of the schema to use, e.g.
#                   'iati-activities-schema.xsd'
#         """
#         self.trees = [ET.parse(schema) for schema in schemas]
# 
#     def get_schema_element(self, tag_name, name_attribute):
#         """
#         Return the specified element from the schema.
# 
#         tag_name -- the name of the tag in the schema, e.g. 'complexType'
#         name_attribute -- the value of the 'name' attribute in the schema, ie.
#                           the name of the element/type etc. being described,
#                           e.g. iati-activities
#         """
#         for tree in self.trees:
#             schema_element = tree.find(
#                 "xsd:{0}[@name='{1}']".format(tag_name, name_attribute),
#                 namespaces=namespaces,
#             )
#             if schema_element is not None:
#                 return schema_element
#         return schema_element
# 
#     def element_loop(self, element, path):
#         """
#         Return information about the children of the supplied element.
#         """
#         a = element.attrib
#         type_elements = []
#         if "type" in a:
#             complexType = self.get_schema_element("complexType", a["type"])
#             if complexType is not None:
#                 type_elements = complexType.findall(
#                     "xsd:choice/xsd:element", namespaces=namespaces
#                 ) + complexType.findall(
#                     "xsd:sequence/xsd:element", namespaces=namespaces
#                 )
# 
#         children = (
#             element.findall(
#                 "xsd:complexType/xsd:choice/xsd:element", namespaces=namespaces
#             )
#             + element.findall(
#                 "xsd:complexType/xsd:sequence/xsd:element", namespaces=namespaces
#             )
#             + element.findall(
#                 "xsd:complexType/xsd:all/xsd:element", namespaces=namespaces
#             )
#             + type_elements
#         )
#         child_tuples = []
#         for child in children:
#             a = child.attrib
#             if "name" in a:
#                 child_tuples.append(
#                     (a["name"], child, None, a.get("minOccurs"), a.get("maxOccurs"))
#                 )
#             else:
#                 child_tuples.append(
#                     (a["ref"], None, child, a.get("minOccurs"), a.get("maxOccurs"))
#                 )
#         return child_tuples
# 
#     def create_schema_dict(self, parent_name, parent_element=None):
#         """
#         Create a nested OrderedDict representing the structure (and order!) of
#         elements in the provided schema.
#         """
#         if parent_element is None:
#             parent_element = self.get_schema_element("element", parent_name)
#         if parent_element is None:
#             return {}
# 
#         return OrderedDict(
#             [
#                 (name, self.create_schema_dict(name, element))
#                 for name, element, _, _, _ in self.element_loop(parent_element, "")
#             ]
#         )
# 
# def sort_element(element, schema_subdict):
#     """
#     Sort the given element's children according to the order of schema_subdict.
#     """
#     children = list(element)
#     for child in children:
#         element.remove(child)
#     keys = list(schema_subdict.keys())
# 
#     def index_key(x):
#         if x.tag in keys:
#             return keys.index(x.tag)
#         else:
#             return len(keys) + 1
# 
#     for child in sorted(children, key=index_key):
#         element.append(child)
#         sort_element(child, schema_subdict.get(child.tag, {}))


# Path: flattentool/xml_output.py
from collections import OrderedDict
from warnings import warn
from flattentool.exceptions import DataErrorWarning
from flattentool.sort_xml import XMLSchemaWalker, sort_element
    import lxml.etree as ET
    import xml.etree.ElementTree as ET

        warn(str(e), DataErrorWarning)
        return

    if USING_LXML:
        data = sort_attributes(data)

    for k, v in data.items():
        if type(v) == list:
            for item in v:
                child_to_xml(el, k, item, nsmap=nsmap)
        else:
            child_to_xml(el, k, v, toplevel=toplevel, nsmap=nsmap)
    return el


def toxml(
    data,
    xml_root_tag,
    xml_schemas=None,
    root_list_path="iati-activity",
    xml_comment=None,
):
    nsmap = {
        # This is "bound by definition" - see https://www.w3.org/XML/1998/namespace
        "xml": "http://www.w3.org/XML/1998/namespace"
    }
    root = dict_to_xml(data, xml_root_tag, nsmap=nsmap)
    if xml_schemas is not None:
        schema_dict = XMLSchemaWalker(xml_schemas).create_schema_dict(root_list_path)
        for element in root:

            sort_element(element, schema_dict)