9.8. Add a cellspacing Attribute to <table> Tags That Do Not Already Include It

Problem

You want to search through an (X)HTML file and add cellspacing="0" to all tables that do not already include a cellspacing attribute.

This recipe serves as an example of adding an attribute to XML-style tags that do not already include it. You can modify the regexes and replacement strings in this recipe to use whatever tag and attribute names and values you prefer.

Solution

Solution 1, simplistic

You can use negative lookahead to match <table> tags that do not contain the word cellspacing, as follows:

<table\b(?![^>]*?\scellspacing\b)([^>]*)>
Regex options: Case insensitive
Regex flavors: .NET, Java, JavaScript, PCRE, Perl, Python, Ruby

Here’s the regex again in free-spacing mode:

<table \b            # Match "<table", as a complete word
(?!                  # Not followed by:
  [^>]*?             #   Any attributes, etc.
  \s cellspacing \b  #   "cellspacing", as a complete word
)
([^>]*)              # Capture attributes, etc. to backreference 1
>
Regex options: Case insensitive
Regex flavors: .NET, Java, XRegExp, PCRE, Perl, Python, Ruby

Solution 2, more reliable

The following regex works exactly the same as Solution 1, except that both instances of the negated character class [^>] are replaced with (?:[^>"']|"[^"]*"|'[^']*'). This longer pattern passes over double- and single-quoted attribute values in one step:

<table\b(?!(?:[^>"']|"[^"]*"|'[^']*')*?\scellspacing\b)↵
((?:[^>"']|"[^"]*"|'[^']*')*)>
Regex options: Case insensitive
Regex flavors: .NET, Java, JavaScript, ...

Get Regular Expressions Cookbook, 2nd Edition now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.