Python Forum
[SOLVED] [BeautifulSoup] Adding newline before+after new element?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[SOLVED] [BeautifulSoup] Adding newline before+after new element?
#1
Question 
Hello,

Google didn't help to find how to add a newline before and after a new element. Does someone know?

def create_new_tag(soup,name,text=""):
	new_tag = soup.new_tag(name)
	new_tag.string = text
	return new_tag

soup_out = BeautifulSoup(open("blah.tmpl", 'r',encoding='utf-8'), "lxml")
body = soup_out.body
if not body:
	print("Body not found")
	exit()
else:
	#TODO how to add \n before+after new tag?
	#<h2 id="comments"></h2><blah>my text</blah>
	body.select_one('h2[id="comments"]').insert_after(create_new_tag(soup_out,"blah","my text"))
	print(body)
Thank you.
Reply
#2
XGrok answer:

To add a **horizontal line** (i.e. <hr> tag) — or any other tag — using **BeautifulSoup** in Python, you need to:

1. Create a new tag using the .new_tag() method
2. Insert/append that tag into an existing element in the parse tree

Here are the most common and correct ways (BeautifulSoup 4):

### 1. Most common — Append at the end of a container

from bs4 import BeautifulSoup

html = """
<div class="content">
    <p>First paragraph</p>
    <p>Second paragraph</p>
</div>
"""

soup = BeautifulSoup(html, "html.parser")

# Find where you want to add the line
container = soup.find("div", class_="content")

# Create the <hr> tag
hr = soup.new_tag("hr")           # you can also add attrs: soup.new_tag("hr", id="sep", class_="thin")

# Add it at the end
container.append(hr)

# Optional: add attributes later if needed
# hr["class"] = "separator"
# hr["style"] = "border: 2px dashed red;"

print(soup.prettify())
**Result (relevant part):**

Output:
<div class="content"> <p> First paragraph </p> <p> Second paragraph </p> <hr/> </div>
### 2. Insert at specific position (recommended when order matters)

# Insert after first <p>
ps = container.find_all("p")
if len(ps) >= 1:
    ps[0].insert_after(hr)          # ← very readable & commonly used

# OR — more precise control with index
container.insert(1, hr)             # insert as 2nd child (0-based index)
### 3. Quick one-liners people often use


# After a specific element
soup.find("p", string="First paragraph").insert_after(soup.new_tag("hr"))

# At the beginning of body
soup.body.insert(0, soup.new_tag("hr"))

# Before last child
soup.body.contents[-1].insert_before(soup.new_tag("hr"))
### Summary — Main methods that allow adding tags

| Method | What it does | When to use | Modifies in place? |
|---------------------|----------------------------------------------------|------------------------------------------|--------------------|
| .new_tag("hr") | Creates brand new tag (must be called on Soup object) | Always — first step | — |
| .append(tag) | Adds as **last** child | Quick addition at end | Yes |
| .insert(index, tag) | Inserts at specific child position (0-based) | Need exact position | Yes |
| .insert_before(tag) | Inserts immediately before this element | "Put line before this paragraph" | Yes |
| .insert_after(tag) | Inserts immediately after this element | Very common: "line after heading" | Yes |
| .replace_with() | Replaces existing element/string with new one | When replacing placeholder/comment | Yes |

### Important Rules / Gotchas

- You **must** create tags with soup.new_tag() (not BeautifulSoup("<hr>") or manually with strings) → otherwise .append() / .insert() may not behave correctly or may escape content
- .append() / .insert() only accept Tag, NavigableString, or other PageElement objects — **not raw strings** like "<hr>"
- <hr> is a **void element** → BeautifulSoup outputs it as <hr/> (self-closing) in XHTML-style parsers or <hr> in html5lib/html.parser (depending on formatter)
- Always work on the **same** BeautifulSoup object when creating new tags (soup.new_tag(), not other_soup.new_tag())

Quick recommended pattern (most readable):

container = soup.select_one("div.content")
if container:
    hr = soup.new_tag("hr")
    # hr["class"] = "my-line"
    last_p = container.find_all("p")[-1]        # or any other reference element
    last_p.insert_after(hr)
That's basically all you need for 95% of cases when adding lines (<hr>) or any other elements with BeautifulSoup.
DeaD_EyE likes this post
Reply
#3
Is there some good reason you would not do this in an html editor, where you can see what is happening, and what effect it will have on your html in the browser?
Reply
#4
BeautifulSoup itself doesn’t automatically handle formatting (like newlines) the way a code formatter would — it mainly manipulates the DOM structure. If you want to add a newline before and after a new element, you need to explicitly insert NavigableString("\n") objects.

Here’s how you can do it:

from bs4 import BeautifulSoup, NavigableString

html = "<div><p>First</p><p>Second</p></div>"
soup = BeautifulSoup(html, "html.parser")

new_tag = soup.new_tag("p")
new_tag.string = "Inserted"

# Add newline before and after
newline = NavigableString("\n")

target = soup.find_all("p")[0]
target.insert_after(newline)
target.insert_after(new_tag)
target.insert_after(NavigableString("\n"))

print(soup.prettify())
Alternatively, you can wrap the insertion like this for cleaner control:

target.insert_after(NavigableString("\n"))
target.insert_after(new_tag)
target.insert_after(NavigableString("\n"))
Important notes:

prettify() will format output nicely, but it may not preserve your exact manual spacing.

If you're modifying HTML for readability (not rendering), using prettify() is usually easier.

If you're generating HTML for browsers, newlines usually don’t affect visual rendering unless inside <pre> or similar tags.

If you tell me where you're inserting (before, after, inside parent, etc.), I can tailor the snippet more precisely.
buran write Feb-25-2026, 08:25 AM:
Please post all code, output and errors (it it's entirety) between their respective tags. Refer to BBCode help topic on how to post. Use the "Preview Post" button to make sure the code is presented as you expect before hitting the "Post Reply/Thread" button.
Pedroski55 likes this post
A powerful gpu shader test tool helps measure real-time graphics performance by stressing your GPU with shader-heavy workloads. It evaluates frame stability, rendering smoothness, and processing efficiency directly in the browser. Ideal for gamers, developers, and hardware enthusiasts who want quick, reliable insight into GPU performance without installing software.
Reply
#5
Hi,

newlines are meaningless in HTML Code between tags, the HTML parsers of browsers don't care. A full webpage could be a single, very long string. If you automate HTML code generation, normally readability doesn't matter - as the code is generated by a machine for a machine.

As you seem to work with some type of template file, it may be worth considering moving the logic into the template file.

Regards, noisefloor
Reply
#6
(Feb-24-2026, 01:21 PM)MarkHenry Wrote: BeautifulSoup itself doesn’t automatically handle formatting (like newlines) the way a code formatter would — it mainly manipulates the DOM structure. If you want to add a newline before and after a new element, you need to explicitly insert NavigableString("\n") objects.

Thanks, that's what I was looking for.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
Question [SOLVED] [BeautifulSoup] A few questions Winfried 2 590 Nov-20-2025, 02:10 PM
Last Post: Winfried
Question [SOLVED] [BeautifulSoup] Why do I get a KeyError? Winfried 2 2,087 Aug-31-2025, 06:45 PM
Last Post: Winfried
  [Solved]Help with BeautifulSoup.getText() Error Extra 5 8,056 Jan-19-2023, 02:03 PM
Last Post: prvncpa

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020