Я хочу использовать разметку как:
<span class="test">Some text that is <strong>bolded</strong> and contains a <a href="#">link</a>.</span>
и найти лучший метод в PHP для удаления диапазона так, чтобы оставалось следующее:
Some text that is <strong>bolded</strong> and contains a <a href="#">link</a>.
Я прочитал многие другие вопросы, связанные с разбором HTML с использованием PHP DOM вместо регулярного выражения, но не смог найти способ разделить промежутки с PHP DOM, оставив содержимое HTML неповрежденным. Конечная цель состоит в том, чтобы убрать документ всех тегов span, оставив их содержимое. Можно ли это сделать с помощью PHP DOM? Есть ли метод, который обеспечивает лучшую производительность и не полагается на синтаксический анализ строк вместо разбора DOM?
Я использовал regex для этого, без каких-либо проблем до сих пор:
/<(\/)?(span)[^>]*>/i
Но мой интерес здесь в том, чтобы стать лучшим программистом PHP. И так как всегда можно отключить регулярное выражение с плохо отформатированной разметкой, я ищу лучший способ. Я также рассмотрел использование strip_tags (), выполнив что-то вроде следующего:
public function strip_tags( $content, $tags_to_strip = array() ) { // All Valid XHTML tags $valid_tags = array( 'a','abbr','acronym','address','area','b','base','bdo','big','blockquote','body','br','button','caption','cite', 'code','col','colgroup','dd','del','dfn','div','dl','DOCTYPE','dt','em','fieldset','form','h1','h2','h3','h4', 'h5','h6','head','html','hr','i','img','input','ins','kbd','label','legend','li','link','map','meta','noscript', 'object','ol','optgroup','option','p','param','pre','q','samp','script','select','small','span','strong','style', 'sub','sup','table','tbody','td','textarea','tfoot','th','thead','title','tr','tt','ul','var' ); // Remove each tag to strip from the valid_tags array foreach ( $tags_to_strip as $tag ){ $ndx = array_search( $tag, $valid_tags ); if ( $ndx !== false ){ unset( $valid_tags[ $ndx ] ); } } // convert valid_tags array into param for strip_tags $valid_tags = implode( '><', $valid_tags ); $valid_tags = "<$valid_tags>"; $content = strip_tags( $content, $valid_tags ); return $content; }
Но это все еще разбор строки, а не разбор DOM. Поэтому, если текст не сформирован, его можно разделить слишком много. Многие люди быстро предлагают использовать простой HTML DOM Parser , но, глядя на исходный код, кажется, что используется регулярное выражение для синтаксического анализа html.
Это можно сделать с помощью DOM PHP5, или есть лучший способ снять метки, оставляя их содержимое неповрежденным. Будет ли плохой практикой использовать Tidy или HTML Purifier для очистки текста, а затем использовать регулярный синтаксический анализатор DREGEX / HTML Simple HTML?
Библиотеки, такие как phpQuery, кажутся слишком тяжелыми для того, что, похоже, должно быть простой задачей.
Я использую следующую функцию для удаления узла без удаления его дочерних элементов:
function DOMRemove(DOMNode $from) { $sibling = $from->firstChild; do { $next = $sibling->nextSibling; $from->parentNode->insertBefore($sibling, $from); } while ($sibling = $next); $from->parentNode->removeChild($from); }
Например:
$dom = new DOMDocument; $dom->load('myhtml.html'); $nodes = $dom->getElementsByTagName('span'); foreach ($nodes as $node) { DOMRemove($node); } echo $dom->saveHTML();
Дала бы вам:
Some text that is <strong>bolded</strong> and contains a <a href="#">link</a>.
Хотя это:
$nodes = $dom->getElementsByTagName('a'); foreach ($nodes as $node) { DOMRemove($node); } echo $dom->saveHTML();
Дала бы вам:
<span class="test">Some text that is <strong>bolded</strong> and contains a link.</span>
Что ж,
По моему опыту, каждый раз, когда я работал с DOM, я немного разбираюсь в производительности, сравнивая с простыми операциями stri.
С вашей функцией вы пытались строго фильтровать действительные теги XHTML, но вам не нужен цикл с ручным сравнением, поскольку вы можете назначить всю эту задачу интерпретатору PHP с помощью собственных функций.
Конечно, вы хорошо комбинировали, чтобы достичь очень хорошей производительности (мне, 0.0002 миллисекунды), но вы можете попытаться объединить функции в одной строке, позволяя каждой функции выполнять свою собственную естественную работу.
Взгляните, и вы поймете, о чем я говорю:
$text = '<span class="test">Some text that is <strong>bolded</strong> and contains a <a href="#">link</a>.</span>'; $validTags = array( 'a','abbr','acronym','address','area','b','base','bdo','big','blockquote','body','br','button','caption','cite', 'code','col','colgroup','dd','del','dfn','div','dl','DOCTYPE','dt','em','fieldset','form','h1','h2','h3','h4', 'h5','h6','head','html','hr','i','img','input','ins','kbd','label','legend','li','link','map','meta','noscript', 'object','ol','optgroup','option','p','param','pre','q','samp','script','select','small','span','strong','style', 'sub','sup','table','tbody','td','textarea','tfoot','th','thead','title','tr','tt','ul','var' ); $tagsToStrip = array( 'span' ); var_dump( strip_tags( $text, sprintf( '<%s>', implode( '><', array_diff( $validTags, $tagsToStrip ) ) ) ) );
Я использовал свой собственный список, но я объединил sprintf (), implode () и array_diff (), чтобы выполнять конкретные задачи для достижения цели.
Надеюсь, это помогло.