This rule raises an issue when HTML elements are inserted into an in-memory document structure using methods that add content nodes with raw HTML strings.

In Python, this specifically refers to BeautifulSoup operations such as insert(), append(), and extend() that add HTML content to the document tree.

Why is this an issue?

Document parsing and manipulation libraries provide APIs for building and modifying HTML and XML document trees. When working with these libraries, you need to add new elements to the document structure programmatically.

A common mistake is to insert raw markup strings directly into the document tree. When you do this, the library treats the string as text content rather than markup. This means all markup special characters get escaped:

As a result, instead of creating actual elements in the document tree, you end up with visible text that looks like markup code on the rendered page. The document structure becomes invalid, and the intended functionality is lost.

Factory methods provided by the library are the correct API for creating new elements programmatically. These methods create proper element objects that integrate seamlessly into the document tree. You specify the element name as the first argument and can pass attributes as additional parameters.

Using factory methods ensures:

In Python’s BeautifulSoup library specifically, this factory method is called new_tag().

What is the potential impact?

The incorrect HTML structure will cause the web page to display escaped HTML text instead of rendering the intended elements. This breaks the application’s functionality and user interface. Users will see literal HTML code like angle brackets and tag names displayed as text instead of the intended page structure.

How to fix it

Replace raw HTML string insertion with the new_tag() factory method. Create the tag object first by calling soup.new_tag() with the tag name and attributes, then insert it into the document tree.

Code examples

Noncompliant code example

from bs4 import BeautifulSoup

soup = BeautifulSoup('<html><body></body></html>', 'html.parser')
soup.body.insert(0, '<div id="file_history"></div>')  # Noncompliant

Compliant solution

from bs4 import BeautifulSoup

soup = BeautifulSoup('<html><body></body></html>', 'html.parser')
new_tag = soup.new_tag('div', id='file_history')
soup.body.insert(0, new_tag)

Resources

Documentation