Изменить заданный c подэлемент в xml с помощью Python - PullRequest
0 голосов
/ 10 февраля 2020

Я начинаю играть с Python, но попал в стену в xml.

Я пытаюсь отредактировать подэлемент xml, который, возможно, хранится не очень обычным способом , он имеет много чисел в виде текста и больше похож на вектор со всеми подэлементами, названными 'double', хотя на самом деле это текст ... тогда я ожидал, что xml будет.

Это Пример такого файла

<simulation>
         <element1>'A'</element1>
         <element2>
              <subelement1>
                   <double>1</double>
                   <double>2</double>
                   <double>3</double>
                   <double>4</double>
                   <double>5</double>
              </subelement1>
              <subelement2>
                   <double>1</double>
                   <double>2</double>
                   <double>3</double>
                   <double>4</double>
                   <double>5</double>
              </subelement2>
         </element2>
</simulation>

Что я хочу сделать, это изменить значения всех дочерних узлов с subelement1, скажем, 10, 20, 30, 40, 50, что-то вроде этого в конце:

<simulation>
         <element1>'A'</element1>
         <element2>
              <subelement1>
                   <double>10</double>
                   <double>20</double>
                   <double>30</double>
                   <double>40</double>
                   <double>50</double>
              </subelement1>
              <subelement2>
                   <double>1</double>
                   <double>2</double>
                   <double>3</double>
                   <double>4</double>
                   <double>5</double>
              </subelement2>
         </element2>
</simulation>

Может получить доступ ко всем узлам, которые я хочу изменить, с помощью этого:

import xml.etree.ElementTree as ET

for elem in root:
    for subelem in elem.findall('.//element1/double'):
        print(subelem.attrib)
        print(subelem.text)

Это показывает числа, которые я хочу изменить (см. Ниже), но я не смог найти способ на самом деле измените их на те, которые мне нужны.

{} 1    {} 2    {} 3    {} 4    {} 5

Если я попытаюсь использовать его как вектор или что-то вроде этого:

for elem in root:
    for subelem in elem.findall('.//element1/double'):
        subelem.text = [10,20,30,40,50]
        print(subelem.text)

В итоге я не заменяю, а добавляю информацию, и результаты:

{} 1 [10,20,30,40,50]
{} 2 [10,20,30,40,50]
{} 3 [10,20,30,40,50]
{} 4 [10,20,30,40,50]
{} 5 [10,20,30,40,50]

Каким будет способ внесения изменений? Большое спасибо.

1 Ответ

2 голосов
/ 10 февраля 2020

Присвоение атрибуту text элемента заменяет значение, оно не добавляется. В вашем тестовом коде должно быть что-то не так.

Вам необходимо убедиться, что вы присвоили строку. ET будет принимать число или список, любой объект на самом деле, но позже будет обрабатывать sh, когда вы попытаетесь сериализовать дерево. Кроме того, нет необходимости перечислять первый уровень элементов до того, как findall, .// скажет ему выполнить поиск по всему поддереву.

import xml.etree.ElementTree as ET

xmltext = """<simulation>
         <element1>'A'</element1>
         <element2>
              <subelement1>
                   <double>1</double>
                   <double>2</double>
                   <double>3</double>
                   <double>4</double>
                   <double>5</double>
              </subelement1>
              <subelement2>
                   <double>1</double>
                   <double>2</double>
                   <double>3</double>
                   <double>4</double>
                   <double>5</double>
              </subelement2>
         </element2>
</simulation>"""

root = ET.fromstring(xmltext)

# to apply a function to each text node
#for subelem in root.findall('.//subelement1/double'):
#    subelem.text = str(int(subelem.text) * 10)

# to replace a known number of text nodes
for subelem in root.findall('.//subelement1/[double]'):
    new_doubles = [10, 20, 30, 40 ,50]
    for elem, dbl in zip(subelem.findall('double'), new_doubles):
        elem.text = str(dbl)
    break

print(ET.tostring(root, encoding="utf-8").decode('utf-8'))

Отпечатки

<simulation>
         <element1>'A'</element1>
         <element2>
              <subelement1>
                   <double>10</double>
                   <double>20</double>
                   <double>30</double>
                   <double>40</double>
                   <double>50</double>
              </subelement1>
              <subelement2>
                   <double>1</double>
                   <double>2</double>
                   <double>3</double>
                   <double>4</double>
                   <double>5</double>
              </subelement2>
         </element2>
</simulation>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...