Intereting Posts

PHP DOM – снятие тегов span, оставляя их содержимое

Я хочу использовать разметку как:

<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 (), чтобы выполнять конкретные задачи для достижения цели.

Надеюсь, это помогло.