Как создать XML-файл с несколькими элементами в python

#python #xml

#python #xml

Вопрос:

Я хочу создать XML-файл с использованием python следующим образом:

 <?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>
  ........
 

мой код:

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

Мой вывод содержит все данные, но все они записаны в одном из «транспортных средств»
вот так:

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

Всегда ли перезаписывается корень?
Как это можно решить?

Комментарии:

1. можете ли вы предоставить образец вашего veh_dict

2. @lrh09 veh_dict — это словарь . Пример внутри: [{'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'}]

3. Откуда вы берете транспортное id средство? Его нет veh_dict .

4. Ваш желаемый XML неправильно сформирован. Чтобы соответствовать правилам, вам нужен корневой тег над vehicle элементами.

Ответ №1:

Добавьте корневой элемент внутри цикла:

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

 

Комментарии:

1. Спасибо за ваш ответ. При выполнении таким образом xml.dom.HierarchyRequestErr: two document elements disallowed появится

2. Чуть не забыл. В XML вам нужно вложить все элементы в один корневой элемент. Итак, вам нужно создать элемент вверху, например vehicles , а затем добавить все вложенные vehicle элементы внутри него. Пожалуйста, проверьте обновленный код

3. Пожалуйста, рассмотрите возможность утверждения ответа, если это помогло 🙂

Ответ №2:

Рассмотрите возможность использования корневых элементов верхнего уровня над <vehicle> элементами, как это требуется для правильно сформированных XML-документов. Кроме того, избегайте повторяющихся строк и используйте ключи внутреннего словаря в качестве переменной итератора. Наконец, используйте диспетчер контекста, with , чтобы записать встроенный XML в файл.

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

Вывод

 <?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>
 

Комментарии:

1. Отлично. Не забудьте способ StackOverflow сказать спасибо !