Если для этого вам подходит регулярное выражение, это работает для меня.(Примечание. Фильтрация комментариев, типа документа и других объектов не включена.
Другие предупреждения; теги могут быть встроены в сценарий, комментарии и другие элементы.)
span Тег ( с атрибутом ) без термина | диапазон атрибутов
'<span
(?=\s)
(?! (?:[^>"\']|(?>".*?"|\'.*?\'))*? (?<=\s) (?:term|range) \s*= )
\s+ (?:".*?"|\'.*?\'|[^>]*?)+
>'
любой тег ( с атрибутом ) без термина | диапазон атрибутов
'<[A-Za-z_:][\w:.-]*
(?=\s)
(?! (?:[^>"\']|(?>".*?"|\'.*?\'))*? (?<=\s) (?:term|range) \s*= )
\s+ (?:".*?"|\'.*?\'|[^>]*?)+
>'
любой тег (* 1031)* без атрибута ) без термина | диапазон атрибутов
'<
(?:
[A-Za-z_:][\w:.-]*
(?=\s)
(?! (?:[^>"\']|(?>".*?"|\'.*?\'))*? (?<=\s) (?:term|range) \s*= )
\s+ (?:".*?"|\'.*?\'|[^>]*?)+
|
/?[A-Za-z_:][\w:.-]*\s*/?
)
>'
Обновление
Альтернатива использованию (?>) конструкции
Ниже приведены регулярные выражения для атрибутов no-'term | range'
Flags = (g) global и (s) dotall
тег span с атрибутом
ссылка: http://regexr.com? 2vrjr
регулярное выражение: <span(?=\s)(?!(?:[^>"\']|"[^"]*"|\'[^\']*\')*?(?<=\s)(?:term|range)\s*=)(?!\s*/?>)\s+(?:".*?"|\'.*?\'|[^>]*?)+>
любой тег с атрибутом
ссылка: http://regexr.com? 2vrju
регулярное выражение: <[A-Za-z_:][\w:.-]*(?=\s)(?!(?:[^>"\']|"[^"]*"|\'[^\']*\')*?(?<=\s)(?:term|range)\s*=)(?!\s*/?>)\s+(?:".*?"|\'.*?\'|[^>]*?)+>
любой тег с атрибутом att или wo / attr
ссылка: http://regexr.com? 2vrk1
регулярное выражение: <(?:[A-Za-z_:][\w:.-]*(?=\s)(?!(?:[^>"\']|"[^"]*"|\'[^\']*\')*?(?<=\s)(?:term|range)\s*=)(?!\s*/?>)\s+(?:".*?"|\'.*?\'|[^>]*?)+|/?[A-Za-z_:][\w:.-]*\s*/?)>
', чтобы соответствовать каждому тегу, кроме тех, которые имеют термин = "иногда"'
ссылка: http://regexr.com? 2vrka
<(?:[A-Za-z_:][\w:.-]*(?=\s)(?!(?:[^>"\']|"[^"]*"|\'[^\']*\')*?(?<=\s)term\s*=\s*(["'])\s*occasionally\s*\1)(?!\s*/?>)\s+(?:".*?"|\'.*?\'|[^>]*?)+|/?[A-Za-z_:][\w:.-]*\s*/?)>