Поиск и замена текста с помощью регулярных выражений Python

Просьба строго не судить: чтобы изучить питон поставил задачу пока работать с текстом.

Суть задачи: Записать значения из последнего списка на те же места где они и стояли

Имею строки в файле XML вида: Вид строк

  1. Ищу отрывок текста в строке text="...." с помощью RegEx, получаю в виде списка друг за другом [Build Cravan, Caravan Menu, Leave]

  2. Перевожу эти значения на язык который мне надо

  3. Потом перевожу их обратно в список допустим [Создать Караван, Меню Каравана, Покинуть]

  4. Как записать значения из второго списка также как они стояли по порядку в текст по шаблону?


Ответы (2 шт):

Автор решения: Алексей Р

Можно использовать re.sub() с указанием функции как аргумента для замены захваченных фрагментов:

import re

xml = '''<?xml version="1.0" encoding="utf-8"?>
<base xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" type="string
<tags>
<tag language="English"/>
</tags>
<strings>
<string id="caravan_build" text="Build Caravan"/>
<string id="caravan_menu" text="Caravan Menu"/>
<string id="caravan_menu_leave" text="Leave"/>
</strings>
</base>'''


def translate_words(words):  # здесь переводите захваченный текст
    return words[0][::-1]    # для примера - реверс текста


xml1 = re.sub(r'(?<=text=").*(?=")', translate_words, xml)
print(xml1)
<?xml version="1.0" encoding="utf-8"?>
<base xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" type="string
<tags>
<tag language="English"/>
</tags>
<strings>
<string id="caravan_build" text="navaraC dliuB"/>
<string id="caravan_menu" text="uneM navaraC"/>
<string id="caravan_menu_leave" text="evaeL"/>
</strings>
</base>

Другой (и, наверное, более правильный способ) - распарсить XML и заменить значения атрибутов:

import xml.etree.ElementTree as ET

xml = '''<?xml version="1.0" encoding="utf-8"?>
<base xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" type="string">
<tags>
<tag language="English"/>
</tags>
<strings>
<string id="caravan_build" text="Build Caravan"/>
<string id="caravan_menu" text="Caravan Menu"/>
<string id="caravan_menu_leave" text="Leave"/>
</strings>
</base>'''
tree = ET.fromstring(xml)
all_name_elements = tree.findall('.//string')
for element in all_name_elements:
    txt = element.get('text')
    element.set('text', txt[::-1])
ET.dump(tree)
<base type="string">
<tags>
<tag language="English" />
</tags>
<strings>
<string id="caravan_build" text="navaraC dliuB" />
<string id="caravan_menu" text="uneM navaraC" />
<string id="caravan_menu_leave" text="evaeL" />
</strings>
</base>
→ Ссылка
Автор решения: Alex Titov

Крайне не рекомндуется работать с XML как с текстом, используйте библиотеки, рекомендую установить lxml. Вот код, там приведен пример корректного XML, который ответ от Алексей Р обработает неверно, там есть атрибут context, атрибут text может встретиься в любом другом элементе, ну а фрагмент CDATA (редко встречающийся) может вообще содержать внутри любой текст.

import lxml.etree as ET
xml = b'''<?xml version="1.0" encoding="utf-8"?>
<base xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" type="string">
<tags>
<tag language="English"/>
</tags>
<strings>
<![CDATA[
text="Build Caravan"
]]>
<string id="caravan_build" text="Build Caravan"/>
<string id="caravan_menu" context="Caravan Menu"/>
<string id="caravan_menu_leave" text="Leave"/>
</strings>
</base>'''

def translate_words(words):  # здесь переводите захваченный текст
    return words[::-1]       # для примера - реверс текста

xml0 = ET.fromstring(xml)

for t in xml0.findall('./strings/string[@text]'):
    t.set('text', translate_words(t.get('text')))

print(ET.tostring(xml0, xml_declaration=True, encoding='utf8').decode('utf8'))

P.S. Вероятно, у Вас работа с файлами, там прямо из файла и в файл есть функции.

P.P.S. Чтобы не путать с соответствием переводимых фраз удобно именно для каждого перевода вызывать функцию

→ Ссылка