Что вы попытка сделать не тривиальна: вы не только должны соответствовать элементам «pgBreak» и всем последующим братьям и сестрам, тогда вы хотите переместить их за пределы родительской области и обернуть братьев и сестер в элементе «p». Забавные вещи.
Следующий код должен дать вам представление о том, как его достичь (ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: пример только, требуется очистка, крайние случаи, вероятно, не обрабатываются). Код намеренно раскоментирован, поэтому вам нужно это выяснить :)
Я немного изменил входной XML, чтобы лучше иллюстрировать функциональность.
import lxml.etree
text = """
<root>
<pgBreak pgId="1"/>
<p>
some text to fill out a para
<pgBreak pgId="2"/>
some more text
<quote> A quoted block </quote>
remainder of para
<pgBreak pgId="3"/>
<p>
blurb
</p>
</p>
</root>
"""
root = lxml.etree.fromstring(text)
for pgbreak in root.xpath('//pgBreak'):
inner = pgbreak.getparent()
if inner == root:
continue
outer = inner.getparent()
pgbreak_index = inner.index(pgbreak)
inner_index = outer.index(inner) + 1
siblings = inner[pgbreak_index+1:]
inner.remove(pgbreak)
outer.insert(inner_index,pgbreak)
if siblings[0].tag != 'p':
p = lxml.etree.Element('p')
p.text = pgbreak.tail
pgbreak.tail = None
for node in siblings:
p.append(node)
outer.insert(inner_index+1,p)
else:
for node in siblings:
inner_index += 1
outer.insert(inner_index,node)
Выход:
<root>
<pgBreak pgId="1"/>
<p>
some text to fill out a para
</p>
<pgBreak pgId="2"/>
<p>
some more text
<quote> A quoted block </quote>
remainder of para
</p>
<pgBreak pgId="3"/>
<p>
blurb
</p>
</root>
Используйте следующую-двойников ось, что-то вроде ' "pgBreak/следующий-собрата :: *"' – tdelaney
@tdelaney я попробовал, что изначально, и это не не достичь ожидаемых результатов. – matchew