2009-10-04 11 views
3

En stock PHP5, ce qui est une bonne expression preg_replace pour faire cette transformation:Remplacer les nouvelles lignes avec des balises BR, mais seulement dans les balises PRE

remplacer les nouvelles lignes avec <br />, mais seulement dans <pre> blocs

(N'hésitez pas à faire des hypothèses simplificatrices et à ignorer les cas de coin.Par exemple, nous pouvons supposer que les balises seront une ligne, et non des choses pathologiques comme)

Texte d'entrée:

<div><pre class='some class'>1 
2 
3 
</pre> 
<pre>line 1 
line 2 
line 3 
</pre> 
</div> 

Sortie:

<div><pre>1<br />2<br />3<br /></pre> 
<pre>line 1<br />line 2<br />line 3<br /></pre> 
</div> 

(contexte Motiver: essayer de fermer 20760 bug dans une extension de SyntaxHighlight_GeSHI wikimedia, et de trouver les mes compétences en PHP (je fais surtout python) ne sont pas à la hauteur).

Je suis ouvert à d'autres solutions, en plus de regexen, mais petit est préféré (à titre d'exemple, la construction de machines d'analyse html est trop lourde).

Répondre

0

Sur la base de quelque chose SilentGhost dit (qui ne montre pas ici pour une raison quelconque):

<?php 
$str = "<div><pre class='some class' >1 
2 
3 
</pre> 
<pre>line 1 
line 2 
line 3 
</pre> 
</div>"; 

$out = "<div><pre class='some class' >1<br />2<br />3<br /></pre> 
<pre>line 1<br />line 2<br />line 3<br /></pre> 
</div>"; 

function protect_newlines($str) { 
    // \n -> <br />, but only if it's in a pre block 
    // protects newlines from Parser::doBlockLevels() 
    /* split on <pre ... /pre>, basically. probably good enough */ 
    $str = " ".$str; // guarantee split will be in even positions 
    //$parts = preg_split('/(<pre .* pre>)/Umsxu',$str,-1,PREG_SPLIT_DELIM_CAPTURE); 
    $parts = preg_split("/(< \s* pre .* \/ \s* pre \s* >)/Umsxu",$str,-1,PREG_SPLIT_DELIM_CAPTURE); 
    foreach ($parts as $idx=>$part) { 
     if ($idx % 2) { 
      $parts[$idx] = preg_replace("/\n/", "<br />", $part); 
     } 
    } 
    $str = implode('',$parts); 
    /* chop off the first space, that we had added */ 
    return substr($str,1); 
} 

assert(protect_newlines($str) === $out); 
?> 
6

Quelque chose comme ça?

<?php 

$content = "<div><pre class='some class'>1 
2 
3 
</pre> 
<pre>line 1 
line 2 
line 3 
</pre> 
</div> 
"; 

function getInnerHTML($Node) 
{ 
    $Body = $Node->ownerDocument->documentElement->firstChild->firstChild; 
    $Document = new DOMDocument();  
    $Document->appendChild($Document->importNode($Body,true)); 
    return $Document->saveHTML(); 
} 

$dom = new DOMDocument(); 
$dom->loadHTML($content); 
$preElements = $dom->getElementsByTagName('pre'); 

if (count($preElements)) { 
    foreach ($preElements as $pre) { 
    $value = preg_replace('/\n|\r\n/', '<br/>', $pre->nodeValue ); 
    $pre->nodeValue = $value; 
    } 

    echo html_entity_decode(getInnerHTML($dom->documentElement)); 
} 
+0

réponse mis à jour avec 'html_entity_decode', retirez-le si vous ne avez pas besoin. –

+0

J'ai juste jeté une regex rapide pour les nouvelles lignes, si vous voyez un problème laissez-moi savoir, pour vous wizards perl regex :) –

+0

Cela échoue à mes fins, en ce que le HTML_entity_decode ajoute en newlines entre les éléments. Ne me blâmez pas, blâmer la classe Parser de wikimedia :) –

Questions connexes