Python Forum
How to modify item in dictionary?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to modify item in dictionary?
#1
Hello,

I'm using the xmltodict module to handle an XML file like a dictionary.

Does Python prevent modifying a dictionary? Is there a work-around?

import xmltodict

with open("input.xml") as f:
	xml = f.read()

doc = xmltodict.parse(xml)
for key in doc['kml']['Document']['Placemark']:
	if "LineString" in key:
		print("Found LS")

		#BUG TypeError: 'str' object does not support item assignment
		key['Style'] = "blah"
Thank you.
Reply
#2
We know doc is a dictionary. We don't know what key is, since we can't see your data (but it appears to be a string).

Depending on the XML, the contents of doc['kml']['Document']['Placemark'] might be other datastructures that you can modify or just strings which you can't. Can you show the relevant section of the xml file?
Reply
#3
Yes, it's a string:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.0">
<Document>
<name>Some name</name>
<Placemark>
<name>Some other name</name>
<LineString>
<coordinates>3.880455,43.605057
3.880504,43.605063
3.922701,43.596438
3.923081,43.595929
3.923408,43.595535
</coordinates>
</LineString>
</Placemark>
</Document>
</kml>


If I find a LineString key (section), I'd like to add a new key in the dictionary at the same level.
Reply
#4
If the key will be named "LineString", why not just look for it directly rather than looping over things?

The key ("LineString") is the name of the entry. You can't modify the key, you modify the container with that key.

The entry here is doc['kml']['Document']['Placemark']['LineString']. You can read that item or modify it.

import xmltodict

with open("note.xml") as f:
    xml = f.read()

doc = xmltodict.parse(xml)
for key in doc['kml']['Document']['Placemark']:
    if "LineString" in key:
        print("Found LineString")

        print("Info in linestring is:")
        print(doc['kml']['Document']['Placemark'][key])
Output:
Found LineString Info in linestring is: OrderedDict([('coordinates', '3.880455,43.605057\n3.880504,43.605063\n3.922701,43.596438\n3.923081,43.595929\n3.923408,43.595535')])
Reply
#5
Thanks, but the problem is not finding if a key named LineString lives in the dictionary, but adding a new key in that section:

for key in doc['kml']['Document']['Placemark']:
	if "LineString" in key:
		print("Found LS")

		#TypeError: 'str' object does not support item assignment
		key['Style'] = "blah"

I need to loop because there might be more than one Placemark section (I simplified the data to show what they look like).
Reply
#6
Found it Smile

for key in doc['kml']['Document']['Placemark']:
	if "LineString" in key:
		print("Found LS")
		doc['kml']['Document']['Placemark']['Style'] = "blah"
Thanks for the help.
Reply
#7
Arg: Doesn't work if the file contains other Placemark sections, that must be ignored since they don't have a LineString item:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.0">
<Document>
<name>Some place</name>
<Placemark>
<name>Some track</name>
<LineString>
<coordinates>3.880455,43.605057
3.880504,43.605063
3.922701,43.596438
3.923081,43.595929
3.923408,43.595535
</coordinates>
</LineString>
</Placemark>
<Placemark>
<name>Some location</name>
<Point>
<coordinates>2.3285601,48.8395985</coordinates>
</Point>
</Placemark> </Document>
</kml>


============

Traceback (most recent call last):
File "C:\Debug.dic.py", line 29, in <module>
doc['kml']['Document']['Placemark']['Style'] = LS
TypeError: list indices must be integers or slices, not str


Should I create a second dictionary, that I can modify at will, fill it with the data parsed by xmltodic, and use that second dictionary as output?
Reply
#8
You can do that, but it won't change the behavior. If you have duplicate items, they can't be dictionary keys, because dictionary keys must be unique. So xmltodict will make them list entries. Let's try to see what's happening here
Output:
OrderedDict([('kml', OrderedDict([('@xmlns', 'http://earth.google.com/kml/2.0'), ('Document', OrderedDict([('name', 'Some place'), ('Placemark', [OrderedDict([('name', 'Some track'), ('LineString', OrderedDict([('coordinates', '3.880455,43.605057\n3.880504,43.605063\n3.922701,43.596438\n3.923081,43.595929\n3.923408,43.595535')]))]), OrderedDict([('name', 'Some location'), ('Point', OrderedDict([('coordinates', '2.3285601,48.8395985')]))])])]))]))])
Ugly, so lets hack a pprettyprint...
Output:
OrderedDict([('kml', OrderedDict([('@xmlns', 'http://earth.google.com/kml/2.0'), ('Document', OrderedDict([('name', 'Some place'), ('Placemark', [OrderedDict([('name', 'Some track'), ('LineString', OrderedDict([('coordinates', '3.880455,43.605057\n' '3.880504,43.605063\n' '3.922701,43.596438\n' '3.923081,43.595929\n' '3.923408,43.595535')]))]), OrderedDict([('name', 'Some location'), ('Point', OrderedDict([('coordinates', '2.3285601,48.8395985')]))])])]))]))])
What's happening here is that 'kml' and 'Document' are keys whose values are other dictionaries. But 'Placemark' (because it is duplicated) is not. Instead it has a value that is a list, and each of the elements are dictionaries. Those inside-the-list dictionaries are for each of the repetitions.

Because the contents of PlaceMark is a list, you can't index into with with "Style" here. The data structure that xmltodict gives you may change based on later data. Only one Placemark, you get a dict. 2 Placemarks, you get a list of dicts.

So the contents within this one are doc['kml']['Document']['Placemark'][0]. You can add your "Style" key there.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  For Loop and Use of Brackets to Modify Dictionary in Tic-Tac-Toe Game new_coder_231013 7 2,239 Dec-28-2021, 11:32 AM
Last Post: new_coder_231013
  Remove an item from a list contained in another item in python CompleteNewb 19 5,714 Nov-11-2021, 06:43 AM
Last Post: Gribouillis
  Modify a dictionary NathanF 2 2,040 Aug-29-2019, 03:36 PM
Last Post: NathanF
  looking fo an expression that yields a dictionary without an item Skaperen 5 2,940 Apr-09-2019, 02:05 AM
Last Post: Skaperen
  curious syntax with dictionary item inselbuch 3 2,758 Mar-09-2019, 04:21 PM
Last Post: ichabod801
  deleting item from dictionary Skaperen 6 3,069 Feb-20-2019, 01:18 AM
Last Post: Skaperen

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020