Объединить значение похожих тегов в один тег
Я пытался объединить значение аналогичного тега и получить вывод в виде одного тега, как показано ниже.
ввод XML:
<root>
<data>
<slide name="file.xml">
<subtitle>Text1</subtitle>
<MainTitle>Text2</MainTitle>
<MainTitle>text3</MainTitle>
</slide>
<slide name="file.xml">
<Title>String1</Title>
<Title>String2</Title>
<Title>String3</Title>
<Title>String4</Title>
<Title>String5</Title>
<Title>String6</Title>
<Title>String7</Title>
<Title>String8</Title>
</slide>
</data>
</root>
Ожидаемый результат:
<root>
<data>
<slide name="file.xml">
<subtitle>Text1</subtitle>
<MainTitle>Text2</MainTitle>
<MainTitle>text3</MainTitle>
</slide>
<slide name="file.xml">
<Title>String</Title>
</slide>
</data>
</root>
Любая помощь могла бы быть полезна. благодарю вас!!
1 ответ
Решение
Вам нужно рекурсивно сгруппировать общие теги. Вот реализация, которая позволяет передать функцию, которая решает, что делать с текстом:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import itertools
import operator
import os.path
from lxml import etree
text = """
<root>
<data>
<slide name="file.xml">
<subtitle>Text1</subtitle>
<MainTitle>Text2</MainTitle>
<MainTitle>text3</MainTitle>
</slide>
<slide name="file.xml">
<Title>String1</Title>
<Title>String2</Title>
<Title>String3</Title>
<Title>String4</Title>
<Title>String5</Title>
<Title>String6</Title>
<Title>String7</Title>
<Title>String8</Title>
</slide>
</data>
</root>
"""
def combine_elements(elements, combine_text=', '.join):
result = []
for key, group in itertools.groupby(elements, operator.attrgetter('tag')):
items = list(group)
first_item = items[0]
# combine only if item don't have children
if len(items) > 1 and not len(first_item):
combined = combine_text([el.text for el in items])
# and if combine_text returned something, e.g. strings have
# common prefix
if combined:
first_item.text = combined
result.append(first_item)
continue
result.extend(items)
elements[:] = result
# recursively combine others
for element in elements:
combine_elements(element, combine_text)
doc = etree.fromstring(text)
combine_elements(doc, os.path.commonprefix)
print etree.tostring(doc)
С помощью os.path.commonprefix()
как объединитель текста, вы получите следующий результат:
<root>
<data>
<slide name="file.xml">
<subtitle>Text1</subtitle>
<MainTitle>Text2</MainTitle>
<MainTitle>text3</MainTitle>
</slide>
<slide name="file.xml">
<Title>String</Title>
</slide>
</data>
</root>
Если вы хотите, чтобы все тексты сочетались с косой чертой /
(например) вы можете использовать следующее:
doc = etree.fromstring(text)
combine_elements(doc, ' / '.join)
Результат:
<root>
<data>
<slide name="file.xml">
<subtitle>Text1</subtitle>
<MainTitle>Text2 / text3</MainTitle>
</slide>
<slide name="file.xml">
<Title>String1 / String2 / String3 / String4 / String5 / String6 / String7 / String8</Title>
</slide>
</data>
</root>