replace_with, unwrap and wrap
Three higher-level methods restructure the tree in one call: replace_with swaps a tag for another node, unwrap removes a tag but keeps its children in place, and wrap encloses a tag in a new parent.
.replace_with(new_tag)
from bs4 import BeautifulSoup
soup = BeautifulSoup("<div><blink>wow</blink></div>", "html.parser")
strong = soup.new_tag("strong")
strong.string = "wow"
soup.blink.replace_with(strong)
print(soup) # <div><strong>wow</strong></div>
.unwrap() - Remove the Tag, Keep the Contents
soup = BeautifulSoup("<p>keep <span>this</span> text</p>", "html.parser")
soup.span.unwrap()
print(soup) # <p>keep this text</p>
unwrap() is ideal for stripping wrappers that add no semantic value (divs, spans around text).
.wrap(new_tag) - Add a Parent
soup = BeautifulSoup("<p>a</p><p>b</p>", "html.parser")
section = soup.new_tag("section")
soup.find_all("p")[1].wrap(section)
print(soup) # <p>a</p><section><p>b</p></section>
wrap() moves the new tag to the position of the wrapped tag and makes the wrapped tag its child.
Choosing Between Them
- Replace the element entirely: replace_with.
- Remove only the wrapper: unwrap (the contents stay, in order).
- Add a container: wrap.
- Remove the element and its contents: use extract() or decompose() instead.
Summary
replace_with() swaps a tag for a new node, unwrap() deletes a tag while keeping its children, and wrap() encloses a tag in a new parent. These three methods cover most restructuring needs, and combine cleanly with new_tag and the insert family for full document transforms.