Удалить пустые теги с помощью RegEx - PullRequest
7 голосов
/ 28 июня 2010

Я хочу удалить пустые теги, такие как <label></label>, <font> </font>, чтобы:

<label></label><form></form>
<p>This is <span style="color: red;">red</span> 
<i>italic</i>
</p>

будет очищено как:

<p>This is <span style="color: red;">red</span> 
<i>italic</i>
</p>

У меня есть этот RegEx в JavaScript, но он удаляет пустые теги, но также удаляет это: "<i>italic</i></p>"

str=str.replace(/<[\S]+><\/[\S]+>/gim, "");

Чего мне не хватает?

Ответы [ 9 ]

21 голосов
/ 28 июня 2010

Regex не для HTML. Если вы все равно используете JavaScript, я бы рекомендовал использовать JQuery DOM

Что-то вроде:

$('*:empty').remove();

В качестве альтернативы:

$("*").filter(function() 
{ 
     return $.trim($(this).html()).length > 0; 
}).remove();
17 голосов
/ 28 июня 2010

В качестве класса персонажа у вас есть "не пробелы", что означает, что "<i>italic</i></p>" будет соответствовать.Первая половина вашего регулярного выражения будет соответствовать "<(i>italic</i)>", а вторая половина "</(p)>".(Я использовал скобки, чтобы показать, что соответствует каждому [\S]+.)

Измените это:

/<[\S]+><\/[\S]+>/

На это:

/<[^\/>][^>]*><\/[^>]+>/

В целом, вы действительно должныиспользовать правильный процессор HTML, но если вы используете HTML-суп, этого должно быть достаточно:)

8 голосов
/ 30 марта 2013

Все ответы с регулярным выражением действительны только

<label></label>

но в случае

<label> </label>
<label>    </label>
<label>
</label> 

попробуйте этот шаблон, чтобы получить все вышеперечисленное

<[^/>]+>[ \n\r\t]*</[^>]+>
3 голосов
/ 28 июня 2010

Вам необходимо /<[\S]+?><\/[\S]+?>/ - разница составляет ? с после + с, чтобы соответствовать «как можно меньшему количеству» (AKA «не жадное соответствие») непробельных символов (хотя 1 или более)вместо простых + s, которые соответствуют "как можно большему числу" (AKA "жадное совпадение").

Исключение регулярных выражений, как рекомендует другой ответ, также является отличной идеей, но яхотел бы отметить важное различие между жадным и не жадным, которое хорошо послужит вам в самых разных ситуациях, когда регулярные выражения оправданы .

2 голосов
/ 28 июня 2010

Мне нравится решение MattMitchell's jQuery, но здесь есть еще один вариант, использующий собственный JavaScript.

function CleanChildren(elem)
{
    var children = elem.childNodes;
    var len = elem.childNodes.length;

    for (var i = 0; i < len; i++)
    {
        var child = children[i];

        if(child.hasChildNodes())
            CleanChildren(child);
        else
            elem.removeChildNode(child);

    }
}
1 голос
/ 26 сентября 2018

Вот современное нативное решение JavaScript; который на самом деле очень похож на jQuery от 2010 года. Я адаптировал его из этого ответа для проекта, над которым я работаю, и подумал, что поделюсь им здесь.

document.querySelectorAll("*:empty").forEach((x)=>{x.remove()});
  • document.querySelectorAll возвращает NodeList; по сути, это массив всех узлов DOM, которые соответствуют селектору CSS, указанному в качестве аргумента.

    • *:empty - это селектор, который выбирает все элементы (* означает «любой элемент»), который является пустым (что означает :empty).

      Это выберет любой пустой элемент внутри всего документа , если вы хотите удалить только пустые элементы из определенной части страницы (т.е. только те, которые находятся внутри какого-то элемента div); Вы можете добавить идентификатор к этому элементу и затем использовать селектор #id *:empty, что означает любой пустой элемент в элементе с идентификатором id.

      Это почти наверняка то, что вы хотите. Технически некоторые важные теги (например, теги <meta>, теги <br>, теги <img> и т. Д.) Являются "пустыми"; поэтому, не указав область действия, вы в конечном итоге удалите некоторые теги, которые вам, вероятно, небезразличны.

  • forEach перебирает каждый элемент в результирующем NodeList и запускает на нем анонимную функцию (x)=>{x.remove()}. x является текущим элементом в списке, и вызов .remove() для него удаляет этот элемент из DOM.

Надеюсь, это кому-нибудь поможет. Удивительно видеть, как далеко зашёл JavaScript за 8 лет; от почти всегда нуждающейся в библиотеке, чтобы написать что-то сложное в сжатой форме, до возможности делать это изначально.

Редактировать

Итак, метод, описанный выше, будет работать нормально в большинстве случаев, но у него есть две проблемы:

  • Такие элементы, как <div> </div>, не обрабатываются как :empty (без пробела между ними). Селекторы уровня 4 CSS исправили это с введением селектора :blank (который похож на пустой, если не учитывать пробелы), но в настоящее время его поддерживает только Firefox (в форме с префиксом поставщика).
  • Самозакрывающиеся теги перехватываются :empty - и с :blank это так же будет.

Я написал чуть большую функцию, которая работает с этими двумя вариантами использования:

document.querySelectorAll("*").forEach((x)=>{
    let tagName = "</" + x.tagName + ">";
    if (x.outerHTML.slice(tagName.length).toUpperCase() == tagName
        && /[^\s]/.test(x.innerHTML)) {
        x.remove();
    }
});

Мы перебираем все элементы на странице. Мы берем имя тега этого элемента (например, если элемент является div, это будет DIV, и используем его для создания закрывающего тега - например, </DIV>.

Этот тег имеет длину 6 символов. Мы проверяем, соответствуют ли последние 6 символов в верхнем регистре элементов HTML. Если это так, мы продолжим. Если это не так, элемент не имеет закрывающего тега и поэтому должен быть самозакрывающимся. Это предпочтительнее, чем список, потому что это означает, что вам не нужно ничего обновлять, если в спецификацию добавляется новый самозакрывающийся тег.

Затем мы проверяем, содержит ли содержимое элемента какие-либо пробелы. /[^\s]/ является рег. [] является набором в RegEx и будет соответствовать любому символу, который появляется внутри него. Если ^ является первым элементом, набор становится отрицательным - он будет соответствовать любому элементу, который НЕ находится в наборе. \s означает пробел - табуляции, пробелы, переносы строк. Так что [^\s] говорит: "любой символ, который не является пробелом".

Сопоставление с этим, если тег не является самозакрывающимся, и его содержимое содержит символ без пробелов, то мы удаляем его.


Конечно, это немного больше и менее элегантно, чем предыдущая строчка. Но это должно работать практически для каждого случая.

1 голос
/ 28 июня 2010

Это проблема жадного регулярного выражения.Попробуйте это:

str=str.replace(/<[\^>]+><\/[\S]+>/gim, "");

или

str=str.replace(/<[\S]+?><\/[\S]+>/gim, "");

В вашем регулярном выражении <[\S]+?> соответствует <i>italic</i> и <\/[\S]+>соответствует </p>

0 голосов
/ 14 февраля 2019

нашел это в коде pen: jQuery, но выполняет свою работу

$('element').each(function() {
  if ($(this).text() === '') {
    $(this).remove();
  }
});

Вам нужно будет изменить элемент так, чтобы он указывал туда, где вы хотите удалить пустые теги.Не указывайте на документ, потому что это приведет к моему ответу на Toastrackenigma

0 голосов
/ 18 июня 2014

Вы можете использовать это text = text.replace(/<[^/>][^>]<em>>\s</em></[^>]+>/gim, "");

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...