Search code examples
pythonxmldictionaryreturn

Printing the xml fields as dictionary


This is the xml file I used:

<fields>
<input_layer name = "Pocket_Substation"/>
<output_layer name = "sub_substation"/>
<field_mapping>
    <field input_name = "dat"  output_name="date" />
    <field input_name = "Type"  output_name="type"/>
    <field input_name = "Class"  output_name="class"/>
    <field input_name = "Land"  output_name="land"/>
    <field input_name = "status"  output_name="status"/>
    <field input_name = "descrp"  output_name="description"/>
    <field input_name = "Loc"  output_name="location"/>
    <field input_name = "voltage" output_name="voltage"/>
    <field input_name = "name"  output_name="owner_name"/>
    <field input_name = "Remarks"  output_name="remarks"/>
</field_mapping>
</fields>

I need the field values in dictionary format (output_name :input_name). The following is my code to print the dictionary but the program returns

unhashable type: 'list' error.

Here is the code:

import xml.etree.ElementTree as ET

def read_field(xml_node, name):
    return [child.get(name) for child in xml_node.iter('field')]

def read_map(xml_node):
    fields = dict()

    for child in xml_node:
        if child.tag == 'field_mapping':
            fields = {field_name : read_field(child, field_name) for field_name 
                 in ['input_name','output_name']}

            return{
                fields['input_name']:fields['output_name']
                }

tree = ET.parse('substation.xml')
root = tree.getroot()
print(read_map(root))

Solution

  • This line is the problem: return { fields['input_name']:fields['output_name'] }

    This says "return a dict containing a single entry with key equal to the list of input names and value equal to the list of output names". Python then complains, because a list can't be a dict key.

    What you presumably wanted to do was return a dict mapping the input names to the output names. To do that, zip the two lists together (creating a single list of tuples) and then convert that to a dict, which will interpret each tuple as a key/value pair.

    So replace the above line with the following:

    return dict(zip(fields['input_name'],fields['output_name']))