Вам необходимо рекурсивно группировать общие теги. Вот реализация, которая позволяет передать функцию, которая решает, что делать с текстом:
#!/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>
Как вы хотите получить String со всех входов - возьмите первую или общую часть? – Mark