Yun Xie
Yun Xie

Reputation: 19

How to create xml file with multiple element in python

I want to create an XML file using python like this:

<?xml version="1.0" encoding="utf-8"?>
  <vehicle id="m0">
     <timestep  pos="2.3000" angle="11.1766" lane="-250709918#7_0" speed="0.0000" time="8.0" 
  </vehicle>

  <vehicle id="m1">
     <timestep  pos="2.3000" angle="11.1766" lane="-250709918#7_0" speed="0.0000" time="8.0" 
  </vehicle>
  ........

my code:

doc = xml.dom.minidom.Document()
root = doc.createElement('vehicle')
for veh in veh_dict:
   root.setAttribute('id', veh)
   doc.appendChild(root)
   for index, value in enumerate(veh_dict[veh]):
       nodeManager = doc.createElement('timestep')
       nodeManager.setAttribute('time', str(veh_dict[veh][index]['time']))
       nodeManager.setAttribute('angle', str(veh_dict[veh][index]['angle']))
       nodeManager.setAttribute('lane', str(veh_dict[veh][index]['lane']))
       nodeManager.setAttribute(' pos', str(veh_dict[veh][index]['pos']))
       nodeManager.setAttribute('speed', str(veh_dict[veh][index]['speed']))
       nodeManager.setAttribute('type', str(veh_dict[veh][index]['type']))
       nodeManager.setAttribute('x', str(veh_dict[veh][index]['x']))
       nodeManager.setAttribute('y', str(veh_dict[veh][index]['y']))
       root.appendChild(nodeManager)
fp = open('Manager.xml', 'w')
doc.writexml(fp, indent='\t', addindent='\t', newl='\n', encoding="utf-8")

My output has all datas, but they are all written in one of the 'vehicle' like this:

<vehicle id="m2.9">
    <timestep  pos="2.3000" angle="11.1766" lane="-250709918#7_0" speed="0.0000" time="8.0" type="custom_moto" x="469.2605" y="5896.8761"/>
    <timestep  pos="3.3001" angle="12.9664" lane="-250709918#7_0" speed="1.0001" time="9.0" type="custom_moto" x="470.1134" y="5907.0132"/>
    <timestep  pos="6.4467" angle="12.2144" lane="-250709918#7_0" speed="3.1466" time="10.0" type="custom_moto" x="470.849" y="5900.3489"/>
    <timestep  pos="12.7147" angle="11.8696" lane="-250709918#7_0" speed="6.2681" time="11.0" 
    .......

Is the root always being overwritten? How can solve it?

Upvotes: 1

Views: 1650

Answers (2)

Parfait
Parfait

Reputation: 107577

Consider using a top-level root above <vehicle> elements as required for well-formed XML documents. Also, avoid the repetitious lines and use the inner dictionary keys as the iterator variable. Finally, use context manager, with, to write built XML to file.

import xml.dom.minidom

# LIST OF DICTS
veh_dicts = [{'x': '469.2605', 'y': '5896.8761', 'time': 8.0, 'lane': '-250709918#7_0', 
              'angle': '11.1766', 'pos': '2.3000', 'speed': '0.0000', 'type': 'custom_moto'}, 
             {'x': '470.1134', 'y': '5907.0132', 'time': 9.0, 'lane': '-250709918#7_0', 
              'angle': '12.9664', 'pos': '3.3001', 'speed': '1.0001', 'type': 'custom_moto'}]

doc = xml.dom.minidom.Document()
root = doc.createElement('vehicles')             # TOP-LEVEL ROOT
doc.appendChild(root)

# ITERATE THROUGH EACH DICT
for i, veh in enumerate(veh_dicts, start=1):
   vehichleElem = doc.createElement('vehicle')
   vehichleElem.setAttribute('id', f'm{i}')      # USES F-STRING (Python 3.6+)
   root.appendChild(vehichleElem)
   
   nodeManager = doc.createElement('timestep')   
   for k in veh.keys():
      nodeManager.setAttribute(k, str(veh[k]))      
   vehichleElem.appendChild(nodeManager)
   
with open('MiniDomXMLBuild.xml', 'w') as fp:     # CONTEXT MANAGER (NO close() NEEDED)
    doc.writexml(fp, addindent='\t', newl='\n', encoding="utf-8")

Output

<?xml version="1.0" encoding="utf-8"?>
<vehicles>
    <vehicle id="m1">
        <timestep angle="11.1766" lane="-250709918#7_0" pos="2.3000" speed="0.0000" time="8.0" type="custom_moto" x="469.2605" y="5896.8761"/>
    </vehicle>
    <vehicle id="m2">
        <timestep angle="12.9664" lane="-250709918#7_0" pos="3.3001" speed="1.0001" time="9.0" type="custom_moto" x="470.1134" y="5907.0132"/>
    </vehicle>
</vehicles>

Upvotes: 0

Harshana
Harshana

Reputation: 5476

Add the root element inside the loop:

import xml.dom.minidom

doc = xml.dom.minidom.Document()
topElem = doc.createElement('vehicles')

for veh in veh_dict:
   for index, value in enumerate(veh_dict[veh]):
       root = doc.createElement('vehicle')
       root.setAttribute('id', veh)
       doc.appendChild(root)
       nodeManager = doc.createElement('timestep')
       nodeManager.setAttribute('time', str(veh_dict[veh][index]['time']))
       nodeManager.setAttribute('angle', str(veh_dict[veh][index]['angle']))
       nodeManager.setAttribute('lane', str(veh_dict[veh][index]['lane']))
       nodeManager.setAttribute(' pos', str(veh_dict[veh][index]['pos']))
       nodeManager.setAttribute('speed', str(veh_dict[veh][index]['speed']))
       nodeManager.setAttribute('type', str(veh_dict[veh][index]['type']))
       nodeManager.setAttribute('x', str(veh_dict[veh][index]['x']))
       nodeManager.setAttribute('y', str(veh_dict[veh][index]['y']))
       root.appendChild(nodeManager)
       topElem.appendChild(root)
fp = open('Manager.xml', 'w')
doc.writexml(fp, indent='\t', addindent='\t', newl='\n', encoding="utf-8")

Upvotes: 2

Related Questions