2015-11-18 1 views
2

Я должен удалить все содержимое (и теги) между тегами в строке PHP, полученной из файла_файла_определения общего URL-адреса веб-сайта. Я использую выражение RegEx:PHP - удалить все содержимое внутри <script> и CDATA строки HTML

preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', "", $string); 

Он отлично работает, но моя проблема заключается в том, что, если сценарий содержит тег CDATA, он не будет работать. Пример строки будет:

<script type='text/javascript'> 
/* <![CDATA[ */ 
var variable = {"ajax":"....."} 
/* ]]> */ 
</script> 

Я думаю, что проблема с теми «/ » и « /» тегов.


Я уже искал в гугле и на переполнение стека, но Ther не вопрос с конкретным типом CDATA тега (с/* и * /), так что ничего не работает.

Любое предложение?

Edit: Как Стив ответил, я теперь с помощью кода, как это:

foreach($dom->getElementsByTagName('script') as $scripttag){ 
$scripttag->parentNode->removeChild($scripttag); 
} 

И тогда у меня есть:

foreach($dom->getElementsByTagName('ins') as $string) { 
    $string2 .= $string->nodeValue; 
    $string2 .= ' '; 
} 

Но что возвращает $ string2 с сценарий теги внутри ,

EDIT 2 (решаемая): С помощью Стива, я обнаружил, что с помощью Xpath решает эту проблему:

$xpath = new DOMXpath($dom); 
foreach ($xpath->query('//script') as $node) { 
    $node->parentNode->removeChild($node); 
} 

, который удаляет теги сценария и внутри другого тега, например:

<ins><script>First JS</script></ins> 
<ins>Hello</ins> 
<script>Second JS</script> 

Выведет

Hello 

Спасибо всем за помощь!

+1

регулярное выражение для HTML разбора не является хорошей идеей. И не забывайте снимать

+0

В чем проблема? Я вижу, что он работает [«красиво»] (https://regex101.com/r/kS2oB7/1) (конечно, только с предоставленным примером). –

+1

@stribizhev, который является проблемой разбора html с регулярным выражением, так как с точки зрения злоумышленника я не соблюдаю правила .... https://regex101.com/r/zV1yA2/1 – ins0

ответ

2

Dont использовать регулярное выражение для этого использовать правильный HTML Parser как DOMDocument:

$dom = new DOMDocument('1.0', 'utf-8'); 
$dom->loadHTML($html); 
//removing elements from a nodelist resets the internal pointer, so traverse backwards: 
$elements = $dom->getElementsByTagName('script'); 
$count = $elements->length; 
while(--$count){ 
    $elements->item($count)->parentNode->removeChild($elements->item($count)); 
} 

//you can do further dom manipulation here if needed 
$insertContents=''; 
foreach($dom->getElementsByTagName('ins') as $insert){ 
    $insertContents .= $insert->nodeValue . ' '; 
} 
//if you need the complete html at all: 
$html = $dom->saveHTML(); 
//your desired string: 
echo $insertContents; 
+0

Привет, спасибо за ответ, но я уже использую DOMDocument для $ dom-> getElementsByTagName ('ins'); Возможно ли использовать другую функцию вместо $ dom-> saveHTML(); сохранить новый объект dom и повторно использовать его для других getElements? (извините за мое незнание о dom) –

+0

Вы можете просто использовать один и тот же экземпляр - вы можете называть 'getElementsByTagName' столько раз, сколько хотите, и только вызывать' saveHTML', когда вы завершаете обработку – Steve

+0

Привет, Стив, извините за мою настойчивость, но если я использую этот код, как вы сказали, он хранит теги сценария. В частности, я делаю это 'foreach ($ dom-> getElementsByTagName ('ins') как $ string) { $ string2. = $ string -> nodeValue; \t $ string2. = ''; \t} ' Но это снова возвращает $ string2 с тегами скриптов ... Извините снова за мое невежество. –