• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OpenDataServices / flatten-tool / 6507626273

13 Oct 2023 11:25AM UTC coverage: 42.006% (-53.7%) from 95.72%
6507626273

Pull #433

github

odscjames
New "Geo" optional dependencies

https://github.com/OpenDataServices/flatten-tool/issues/424
Pull Request #433: New "Geo" optional dependencies

38 of 38 new or added lines in 6 files covered. (100.0%)

1466 of 3490 relevant lines covered (42.01%)

4.16 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

16.18
/flattentool/xml_output.py
1
from collections import OrderedDict
10✔
2
from warnings import warn
10✔
3

4
from flattentool.exceptions import DataErrorWarning
10✔
5
from flattentool.sort_xml import XMLSchemaWalker, sort_element
10✔
6

7
try:
10✔
8
    import lxml.etree as ET
10✔
9

10
    # If we're using lxml we have to do some extra work to support namespaces,
11
    # so we have a variable to check whether we're using lxml:
12
    USING_LXML = True
10✔
13
    # Note that lxml is now "required" - it's listed as a requirement in
14
    # setup.py and is needed for the tests to pass.
15
    # However, stdlib etree still exists as an unsupported feature.
16
except ImportError:
×
17
    import xml.etree.ElementTree as ET
×
18

19
    USING_LXML = False
×
20
    warn("Using stdlib etree may work, but is not supported. Please install lxml.")
×
21

22

23
def sort_attributes(data):
10✔
24
    attribs = []
×
25
    other = []
×
26
    for k, v in data.items():
×
27
        (other, attribs)[k.startswith("@")].append((k, v))
×
28
    return OrderedDict(sorted(attribs) + other)
×
29

30

31
def child_to_xml(parent_el, tagname, child, toplevel=False, nsmap=None):
10✔
32
    if hasattr(child, "items"):
×
33
        child_el = dict_to_xml(child, tagname, toplevel=False, nsmap=nsmap)
×
34
        if child_el is not None:
×
35
            parent_el.append(child_el)
×
36
    else:
37
        if tagname.startswith("@"):
×
38
            if USING_LXML and toplevel and tagname.startswith("@xmlns"):
×
39
                nsmap[tagname[1:].split(":", 1)[1]] = str(child)
×
40
                return
×
41
            try:
×
42
                attr_name = tagname[1:]
×
43
                if USING_LXML and ":" in attr_name:
×
44
                    attr_name = (
×
45
                        "{"
46
                        + nsmap.get(attr_name.split(":", 1)[0], "")
47
                        + "}"
48
                        + attr_name.split(":", 1)[1]
49
                    )
50
                parent_el.attrib[attr_name] = str(child)
×
51
            except ValueError as e:
×
52
                warn(str(e), DataErrorWarning)
×
53
        elif tagname == "text()":
×
54
            parent_el.text = str(child)
×
55
        else:
56
            raise ("Everything should end with text() or an attribute!")
×
57

58

59
def dict_to_xml(data, tagname, toplevel=True, nsmap=None):
10✔
60
    if USING_LXML and ":" in tagname and not toplevel:
×
61
        tagname = (
×
62
            "{"
63
            + nsmap.get(tagname.split(":", 1)[0], "")
64
            + "}"
65
            + tagname.split(":", 1)[1]
66
        )
67
    try:
×
68
        if USING_LXML:
×
69
            el = ET.Element(tagname, nsmap=nsmap)
×
70
        else:
71
            el = ET.Element(tagname)
×
72
    except ValueError as e:
×
73
        warn(str(e), DataErrorWarning)
×
74
        return
×
75

76
    if USING_LXML:
×
77
        data = sort_attributes(data)
×
78

79
    for k, v in data.items():
×
80
        if type(v) == list:
×
81
            for item in v:
×
82
                child_to_xml(el, k, item, nsmap=nsmap)
×
83
        else:
84
            child_to_xml(el, k, v, toplevel=toplevel, nsmap=nsmap)
×
85
    return el
×
86

87

88
def toxml(
10✔
89
    data,
90
    xml_root_tag,
91
    xml_schemas=None,
92
    root_list_path="iati-activity",
93
    xml_comment=None,
94
):
95
    nsmap = {
×
96
        # This is "bound by definition" - see https://www.w3.org/XML/1998/namespace
97
        "xml": "http://www.w3.org/XML/1998/namespace"
98
    }
99
    root = dict_to_xml(data, xml_root_tag, nsmap=nsmap)
×
100
    if xml_schemas is not None:
×
101
        schema_dict = XMLSchemaWalker(xml_schemas).create_schema_dict(root_list_path)
×
102
        for element in root:
×
103
            sort_element(element, schema_dict)
×
104
    if xml_comment is None:
×
105
        xml_comment = "XML generated by flatten-tool"
×
106
    comment = ET.Comment(xml_comment)
×
107
    root.insert(0, comment)
×
108
    if USING_LXML:
×
109
        return ET.tostring(
×
110
            root, pretty_print=True, xml_declaration=True, encoding="utf-8"
111
        )
112
    else:
113
        return ET.tostring(root)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc