diff options
Diffstat (limited to 'grc/core/ParseXML.py')
-rw-r--r-- | grc/core/ParseXML.py | 67 |
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) |