Here's one way to do it. It's not that easy and pythonic though. Personally I don't like the solution, but it should be a good start for you. I bet there is a more beautiful and short way to do the same.
The idea is to iterate over all elements that don't have children. For every such element iterate recursively over it's parents until we hit body
:
from bs4 import BeautifulSoup, Tag
data = """
your xml goes here
"""
soup = BeautifulSoup(data)
for element in soup.body.find_all():
children = element.find_all()
if not children:
tag = Tag(name=element.name)
tag.string = element.string
for parent in element.parentGenerator():
parent = Tag(name=parent.name)
parent.append(tag)
tag = parent
if tag.name == 'body':
break
print tag
It produces:
<body><p>Example</p></body>
<body><ul><li><ul><li>1</li></ul></li></ul></body>
<body><ul><li><ul><li>2</li></ul></li></ul></body>
<body><ul><li><ul><li>3</li></ul></li></ul></body>
<body><ul><li><ul><li>4.1</li></ul></li></ul></body>
<body><ul><li><ul><li>4.2</li></ul></li></ul></body>
UPD (writing parent's text too):
soup = BeautifulSoup(data)
for element in soup.body.find_all():
children = element.find_all()
if not children:
tag = Tag(name=element.name)
tag.string = element.string
for parent in element.parentGenerator():
parent_tag = Tag(name=parent.name)
if parent.string:
parent_tag.string = parent.string
parent_tag.append(tag)
tag = parent_tag
if tag.name == 'body':
break
print tag
Hope that helps.