Coverage for pyguymer3/elem2dict.py: 81%
26 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
1#!/usr/bin/env python3
3# Define function ...
4def elem2dict(
5 elem,
6 /,
7 *,
8 debug = __debug__,
9):
10 """Convert a XML element into a Python dictionary
12 This function accepts a XML element and recursively turns it in to a Python
13 dictionary.
15 Parameters
16 ----------
17 elem : lxml.etree._Element
18 the XML element
19 debug : bool, optional
20 print debug messages
22 Returns
23 -------
24 ans : dict
25 the XML element as a Python dictionary
27 Notes
28 -----
29 If present, non-empty text will be mapped to a "$$TEXT$$" dictionary field
30 (it is assumed that the XML does not contain any tags called "$$TEXT$$"
31 otherwise). If present, non-empty attributes will be mapped to "::KEY::"
32 dictionary fields (it is assumed that the XML does not contain any tags
33 called "::KEY::" otherwise). If present, child elements will be mapped to
34 "KEY" dictionary fields. If multiple child elements have identical tag names
35 then the "KEY" dictionary field will be a list of them.
37 Copyright 2017 Thomas Guymer [1]_
39 References
40 ----------
41 .. [1] PyGuymer3, https://github.com/Guymer/PyGuymer3
42 """
44 # Initialize dictionary ...
45 ans = {}
47 # Check if it has text ...
48 if elem.text:
49 # Check that the text isn't empty ...
50 if elem.text.strip():
51 ans["$$TEXT$$"] = elem.text
52 elif debug:
53 print(f"INFO: Skipping empty text in \"{elem.tag}\".")
55 # Loop over attributes ...
56 for key, value in elem.attrib.iteritems():
57 # Check that the attribute isn't empty ...
58 if value.strip():
59 # Check if the attribute can be dealt with specially ...
60 if value.isdigit():
61 ans[f"::{key}::"] = int(value)
62 elif value.lower() == "true":
63 ans[f"::{key}::"] = True
64 elif value.lower() == "false":
65 ans[f"::{key}::"] = False
66 else:
67 ans[f"::{key}::"] = value
68 elif debug:
69 print(f"INFO: Skipping empty \"{key}\" attribute in \"{elem.tag}\".")
71 # Loop over children ...
72 for child in elem.iterchildren():
73 # Convert child to a dictionary ...
74 value = elem2dict(child, debug = debug)
76 # Check if a field already exists ...
77 if child.tag in ans:
78 # Check if the field is already a list ...
79 if isinstance(ans[child.tag], list):
80 # Append to list ...
81 ans[child.tag].append(value)
82 else:
83 # Convert the field to a list ...
84 ans[child.tag] = [ans[child.tag], value]
85 else:
86 # Set field ...
87 ans[child.tag] = value
89 # Return answer ...
90 return ans