If I wanted to replace "John Doe" if it's not inside a tag, I would do this:
$str = preg_replace('/John Doe(?![^<>]*+>)/i', $new_name, $str);
(?![^<>]*+>)
is a negative lookahead; it says "if there are any angle brackets ahead of this point, the first one is not a closing bracket." That's not foolproof, since attribute values can contain angle brackets, but in my experience they rarely do.
Regexes are fundamentally incompatible with HTML; even with the advanced features offered by the preg_
suite, like lookarounds and possessive quantifiers, you often have to rely on simplifying assumptions like no angle brackets in attribute values. I wouldn't even attempt this job with the much-more-limited ereg_
functions.