Как вставить большое количество XML в другой файл XML с помощью Python? - PullRequest
1 голос
/ 26 сентября 2019

Это очень похоже на этот вопрос: Вставка XML-документа в существующий XML с Python , но мне нужно иметь возможность вставлять много разных XML-документов со многими атрибутами в глубоко вложенные части существующего XML-документагде субэлементы имеют одно и то же имя.Вот MWE без атрибутов, чтобы загромождать вещи

Основной документ, в который нужно вставить элементы:

<a><b1><array><c1></c1><c1></c1><c1></c1></array></b1><b2></b2></a>

XML-код, который я хочу вставить:

<f><g><h2></h2><h1></h1></g></f>

Вывод, который я хочу:

<a>
   <b1>
      <array>
         <c1 />
         <c1>
            <f>
               <g>
                  <h2 />
                  <h1 />
               </g>
            </f>
         </c1>
         <c1 />
      </array>
   </b1>
   <b2 />
</a>

Мой текущий код Python:

import xml.etree.ElementTree as ET 

top_xml = ET.fromstring("<a><b1><array><c1></c1></array></b1><b2></b2></a>")
bottom_xml = ET.fromstring("<f><g><h2></h2><h1></h1></g></f>")

#want to insert `bottom_xml` under the <c1> tag

, вот где я застрял.ElementTree.insert и ElementTree.append работают над верхним элементом.Я видел другие ответы, использующие ElementTree.subelement для добавления простых элементов xml к подэлементам, но ручное воссоздание структуры xml bottom_xml, когда он может иметь глубину в сотни строк, кажется громоздким.

1 Ответ

1 голос
/ 26 сентября 2019

Использование find для получения узла, в который вы хотите вставить:

 top_xml = ET.fromstring("<a><b1><array><c1></c1></array></b1><b2></b2></a>")

 bottom_xml = ET.fromstring("<f><g><h2></h2><h1></h1></g></f>")

 insert_node = top_xml.find('.//c1')

 insert_node.append(bottom_xml)

Тогда результат будет:

In [31]: print(ET.tostring(top_xml).decode())
<a><b1><array><c1><f><g><h2 /><h1 /></g></f></c1></array></b1><b2 /></a>

Это работает, так какобъект, извлеченный с помощью find, все еще является частью корневого объекта, и любые сделанные вами мутации отражаются обратно на корневой объект.

Подробнее о xpath выражениях, поддерживаемых с помощью find, можно найти здесь

Если вы хотите что-то более продвинутое, я предлагаю использовать lxml

Редактировать

Исходя из вашего вопроса, который вы хотите вставить во второй элемент, вы можете использовать [position]

Например:

insert_node = top_xml.find('.//c1[2]')

Результат:

In [73]: print(ET.tostring(top_xml).decode())
<a><b1><array><c1 /><c1><f><g><h2 /><h1 /></g></f></c1><c1 /></array></b1><b2 /></a>
...