1

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?

4
  • can you provide a sample of your veh_dict Commented Dec 23, 2020 at 6:42
  • @lrh09 veh_dict is a dictionary .The example inside is: [{'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'}] Commented Dec 23, 2020 at 8:16
  • 1
    Where do you get the vehicle id from? It's not in veh_dict. Commented Dec 23, 2020 at 13:37
  • 1
    Your desired XML is not well-formed. To be rules compliant, you need a root tag above vehicle elements. Commented Dec 23, 2020 at 15:53

2 Answers 2

2

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")

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your reply.If executed in this way, xml.dom.HierarchyRequestErr: two document elements disallowed will appear
I almost forgot. In XML, you need to nest all the elements inside one root element. So you have to create an element at the top like vehicles and then add all the nested vehicle elements inside it. Please check the updated code
Please consider approving the answer if it helped :)
0

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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.