summaryrefslogtreecommitdiff
path: root/grc/core/ParseXML.py
diff options
context:
space:
mode:
Diffstat (limited to 'grc/core/ParseXML.py')
-rw-r--r--grc/core/ParseXML.py67
1 files changed, 46 insertions, 21 deletions
diff --git a/grc/core/ParseXML.py b/grc/core/ParseXML.py
index c9f6541ee7..163289ba06 100644
--- a/grc/core/ParseXML.py
+++ b/grc/core/ParseXML.py
@@ -17,9 +17,13 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
+from __future__ import absolute_import
+
from lxml import etree
-from .utils import odict
+import six
+from six.moves import map
+
xml_failures = {}
etree.set_default_parser(etree.XMLParser(remove_comments=True))
@@ -75,17 +79,35 @@ def from_file(xml_file):
the nested data with grc version information
"""
xml = etree.parse(xml_file)
- nested_data = _from_file(xml.getroot())
+
+ tag, nested_data = _from_file(xml.getroot())
+ nested_data = {tag: nested_data, '_instructions': {}}
# Get the embedded instructions and build a dictionary item
- nested_data['_instructions'] = {}
xml_instructions = xml.xpath('/processing-instruction()')
- for inst in filter(lambda i: i.target == 'grc', xml_instructions):
- nested_data['_instructions'] = odict(inst.attrib)
+ for inst in xml_instructions:
+ if inst.target != 'grc':
+ continue
+ nested_data['_instructions'] = dict(inst.attrib)
return nested_data
-def _from_file(xml):
+WANT_A_LIST = {
+ '/block': 'import callback param check sink source'.split(),
+ '/block/param_tab_order': 'tab'.split(),
+ '/block/param': 'option'.split(),
+ '/block/param/option': 'opt'.split(),
+ '/flow_graph': 'block connection'.split(),
+ '/flow_graph/block': 'param'.split(),
+ '/cat': 'cat block'.split(),
+ '/cat/cat': 'cat block'.split(),
+ '/cat/cat/cat': 'cat block'.split(),
+ '/cat/cat/cat/cat': 'cat block'.split(),
+ '/domain': 'connection'.split(),
+}
+
+
+def _from_file(xml, parent_tag=''):
"""
Recursively parse the xml tree into nested data format.
@@ -96,21 +118,24 @@ def _from_file(xml):
the nested data
"""
tag = xml.tag
+ tag_path = parent_tag + '/' + tag
+
if not len(xml):
- return odict({tag: xml.text or ''}) # store empty tags (text is None) as empty string
- nested_data = odict()
+ return tag, xml.text or '' # store empty tags (text is None) as empty string
+
+ nested_data = {}
for elem in xml:
- key, value = _from_file(elem).items()[0]
- if key in nested_data:
- nested_data[key].append(value)
+ key, value = _from_file(elem, tag_path)
+
+ if key in WANT_A_LIST.get(tag_path, []):
+ try:
+ nested_data[key].append(value)
+ except KeyError:
+ nested_data[key] = [value]
else:
- nested_data[key] = [value]
- # Delistify if the length of values is 1
- for key, values in nested_data.iteritems():
- if len(values) == 1:
- nested_data[key] = values[0]
+ nested_data[key] = value
- return odict({tag: nested_data})
+ return tag, nested_data
def to_file(nested_data, xml_file):
@@ -127,7 +152,7 @@ def to_file(nested_data, xml_file):
if instructions:
xml_data += etree.tostring(etree.ProcessingInstruction(
'grc', ' '.join(
- "{0}='{1}'".format(*item) for item in instructions.iteritems())
+ "{0}='{1}'".format(*item) for item in six.iteritems(instructions))
), xml_declaration=True, pretty_print=True, encoding='utf-8')
xml_data += etree.tostring(_to_file(nested_data)[0],
pretty_print=True, encoding='utf-8')
@@ -146,14 +171,14 @@ def _to_file(nested_data):
the xml tree filled with child nodes
"""
nodes = list()
- for key, values in nested_data.iteritems():
+ for key, values in six.iteritems(nested_data):
# Listify the values if not a list
if not isinstance(values, (list, set, tuple)):
values = [values]
for value in values:
node = etree.Element(key)
- if isinstance(value, (str, unicode)):
- node.text = unicode(value)
+ if isinstance(value, (str, six.text_type)):
+ node.text = six.text_type(value)
else:
node.extend(_to_file(value))
nodes.append(node)