Привет, мне нужен скрипт для удаления из строки html всех элементов «li», пустых или содержащих только пробелы. Но также и с внутренним пустым тегом (один или вложенные пустые теги)
Я использую этот preg_replace для успешного удаления только пустого «li». В данном случае 4-я ли.
Но я не знаю, как удалить последнюю букву «li», внутри которой есть пустой «промежуток»… есть какие-нибудь предложения? Спасибо
$contenuto = '<ol style = "margin-top: 0cm; margin-bottom: 0cm;">
<li style = "margin: 0cm 0cm 0cm 47.6px; text-align: justify; line-height: normal; font-size: 11pt; font-family: Calibri, sans-serif; text-indent: 0.4px;"><span style = "font-size: 10.0pt;">x</span></li>
<li style = "margin: 0cm 0cm 0cm 47.6px; text-align: justify; line-height: normal; font-size: 11pt; font-family: Calibri, sans-serif; text-indent: 0.4px;"><span style = "font-size: 10.0pt;">y</span></li>
<li style = "margin: 0cm 0cm 0cm 47.6px; text-align: justify; line-height: normal; font-size: 11pt; font-family: Calibri, sans-serif; text-indent: 0.4px;"><span style = "font-size: 10.0pt;">z</span></li>
<li style = "margin: 0cm 0cm 0cm 47.6px; text-align: justify; line-height: normal; font-size: 11pt; font-family: Calibri, sans-serif; text-indent: 0.4px;"></li>
<li style = "margin: 0cm 0cm 0cm 47.6px; text-align: justify; line-height: normal; font-size: 11pt; font-family: Calibri, sans-serif; text-indent: 0.4px;"><span style = "font-size: 10.0pt; color: red;"> </span></li>
</ol>';
$contenuto = preg_replace('/<li[^>]*>(\s| )*</li>/', '', $contenuto);
echo $contenuto;
Возможно, эта страница может быть полезна, используя DOMDocument/xpath stackoverflow.com/questions/8603237/…
Или расширьте текущее регулярное выражение: <li[^>]*>(?:\s+| |</?span[^>]*>)*</li>
@bobblebubble Ты прав. К счастью, на этой странице есть и другие ответы, а здесь — другие комментарии. Суть остается неизменной: RegEx плохо анализирует HTML, который можно изменить, и этот вопрос, похоже, подразумевает, что это так. Если бы это было не так, вам бы не понадобился RegEx.
Перечитывая ваш вопрос, я думаю Регулярное выражение @CasimiretHippolyte очень хорошо подходит для этого, и оно построено таким удобным образом, что вы можете ориентироваться только на li-теги, добавив предварительный просмотр в начале: <(?=li\b)
. Я забыл, что у вас также есть
, поэтому вам нужно добавить и его после \s*
присоединения (?: \s*)*
, в результате чего получится эта корректировка шаблона Казимира (регулярное выражение101).
Отвечаю на цитацию двух вещей:
Вот мой ответ:
$regex = '/<li[^>]*>(?:\s*|(?:<[^>/]+[^>]*>\s*</[^>]+>)(?:\s*|</?\w+[^>]*>\s*))</li>/s';
$contenuto = preg_replace($regex, '', $contenuto);
Ваш RegEx не работает, когда я меняю <span>
на <b>
: 3v4l.org/EGb2j Вы можете возразить, что это не то, что спрашивают, но я думаю, что это так. В вопросе говорится о «тегах empy» и в качестве примера приводится <span>
.
@KIKOSoftware действительно! Я неправильно понял вопрос, извините, обновил, теперь кажется, что он работает с любым пустым тегом.
Да, вы можете адаптировать свой RegEx, если знаете, к чему адаптироваться. Проблема с HTML в том, что он может сильно различаться. Предположим, тег <b>
окружает тег <span>
, тогда ваше выражение снова не работает: 3v4l.org/0Gmf3 Это может продолжаться бесконечно. Ваше выражение станет настолько сложным, что ни один здравомыслящий человек больше не сможет его понять. Попробуйте другой ответ здесь, обратите внимание, как он справляется с любым HTML и все еще в некоторой степени понятен.
@KIKOSoftware Я ценю возможность знать, когда что использовать, и поддерживать активное обсуждение, не осуждая одно за хорошее, а другое за плохое - все зависит от ситуации. Современные регулярные выражения могут выходить за рамки анализа обычных языков . Шаблон Казимира, о котором я упоминал выше , может работать с вложенными элементами (демо) но для того, кто не привык к регулярным выражениям, его, конечно, сложно читать и адаптировать. Для этой задачи замена регулярного выражения, вероятно, легко превзойдет анализ dom и замену. Однако я бы также использовал здесь решение Гордона (лучше использовать).
XPath для выбора пустых узлов li:
//li[not(normalize-space())]
Запрос XPath — это не то, что вы просили. Но я считаю, что это гораздо более кратко, читабельно и проще в использовании, чем надежное регулярное выражение, которое делает то же самое.
К сожалению, в PHP нет чего-то вроде функции xpath_replace
, которая скрывает весь шаблонный код, необходимый для выполнения того, что preg_replace
делает для регулярных выражений. Поэтому вам придется написать дополнительный код, чтобы получить желаемый результат:
<?php
$html = '<ol style = "margin-top: 0cm; margin-bottom: 0cm;">
<li style = "margin: 0cm 0cm 0cm 47.6px; text-align: justify; line-height: normal; font-size: 11pt; font-family: Calibri, sans-serif; text-indent: 0.4px;"><span style = "font-size: 10.0pt;">x</span></li>
<li style = "margin: 0cm 0cm 0cm 47.6px; text-align: justify; line-height: normal; font-size: 11pt; font-family: Calibri, sans-serif; text-indent: 0.4px;"><span style = "font-size: 10.0pt;">y</span></li>
<li style = "margin: 0cm 0cm 0cm 47.6px; text-align: justify; line-height: normal; font-size: 11pt; font-family: Calibri, sans-serif; text-indent: 0.4px;"><span style = "font-size: 10.0pt;">z</span></li>
<li style = "margin: 0cm 0cm 0cm 47.6px; text-align: justify; line-height: normal; font-size: 11pt; font-family: Calibri, sans-serif; text-indent: 0.4px;"></li>
<li style = "margin: 0cm 0cm 0cm 47.6px; text-align: justify; line-height: normal; font-size: 11pt; font-family: Calibri, sans-serif; text-indent: 0.4px;"><span style = "font-size: 10.0pt; color: red;"> </span></li>
</ol>';
$emptyLists = '//li[not(normalize-space())]';
$dom = new DOMDocument;
$dom->loadHTML($html);
$xpath = new DOMXPath($dom);
foreach($xpath->query($emptyLists) as $node) {
$node->parentNode->removeChild($node);
}
echo $dom->saveHTML($xpath->query('//ol')->item(0));
выведет
<ol style = "margin-top: 0cm; margin-bottom: 0cm;">
<li style = "margin: 0cm 0cm 0cm 47.6px; text-align: justify; line-height: normal; font-size: 11pt; font-family: Calibri, sans-serif; text-indent: 0.4px;"><span style = "font-size: 10.0pt;">x</span></li>
<li style = "margin: 0cm 0cm 0cm 47.6px; text-align: justify; line-height: normal; font-size: 11pt; font-family: Calibri, sans-serif; text-indent: 0.4px;"><span style = "font-size: 10.0pt;">y</span></li>
<li style = "margin: 0cm 0cm 0cm 47.6px; text-align: justify; line-height: normal; font-size: 11pt; font-family: Calibri, sans-serif; text-indent: 0.4px;"><span style = "font-size: 10.0pt;">z</span></li>
</ol>
Спасибо, это отлично работает. Я изменил эту строку, чтобы добавление тега <HTML> не требовалось: $dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
Я не думаю, что saveHTML()
нужно передавать какие-либо параметры. 3v4l.org/o0K0H
Пожалуйста, внимательно прочитайте это прекрасно написанное эссе: Вы не можете анализировать HTML с помощью регулярных выражений.