Frage

Ich bin derzeit mit PHP und einen regulären Ausdruck alle HTML-Kommentare von einer Seite Streifen aus. Das Skript funktioniert gut ... ein zu gut wenig. Es abstreift alle Kommentare einschließlich meinen bedingten Kommentare in der. Hier ist, was ich habe:

<?php
  function callback($buffer)
  {
        return preg_replace('/<!--(.|\s)*?-->/', '', $buffer);
  }

  ob_start("callback");
?>
... HTML source goes here ...
<?php ob_end_flush(); ?>

Da mein regex nicht zu heiß ist, ich habe Probleme beim Versuch, herauszufinden, wie das Muster ändern Bedingte Kommentare auszuschließen wie:

<!--[if !IE]><!-->
<link rel="stylesheet" href="/css/screen.css" type="text/css" media="screen" />
<!-- <![endif]-->

<!--[if IE 7]>
<link rel="stylesheet" href="/css/ie7.css" type="text/css" media="screen" />
<![endif]-->

<!--[if IE 6]>
<link rel="stylesheet" href="/css/ie6.css" type="text/css" media="screen" />
<![endif]-->

Prost

War es hilfreich?

Lösung

Da Kommentare können nicht in HTML verschachtelt werden, kann ein regulärer Ausdruck die Arbeit tun, in der Theorie. Dennoch ist mit einer Art von Parser wäre die bessere Wahl, vor allem, wenn Sie Ihre Eingabe nicht garantiert werden, zu wohlgeformt ist.

Hier ist mein Versuch es. Um nur normale Kommentare zu entsprechen, das funktionieren würde. Es ist durchaus ein Monster, sorry dafür worden. Ich kann es recht ausgiebig getestet haben, wie es scheint es gut zu machen, aber ich gebe keine Garantie.

<!--(?!\s*(?:\[if [^\]]+]|<!|>))(?:(?!-->).)*-->

Erklärung:

<!--                #01: "<!--"
(?!                 #02: look-ahead: a position not followed by:
  \s*               #03:   any number of space
  (?:               #04:   non-capturing group, any of:
    \[if [^\]]+]    #05:     "[if ...]"
    |<!             #06:     or "<!"
    |>              #07:     or ">"
  )                 #08:   end non-capturing group
)                   #09: end look-ahead
(?:                 #10: non-capturing group:
  (?!-->)           #11:   a position not followed by "-->"
  .                 #12:   eat the following char, it's part of the comment
)*                  #13: end non-capturing group, repeat
-->                 #14: "-->"

Steps # 02 und # 11 sind von entscheidender Bedeutung. # 02 stellt sicher, dass die folgenden Zeichen nicht einen bedingten Kommentar angeben. Danach, # 11 stellt sicher, dass die folgenden Zeichen deuten nicht auf das Ende des Kommentars, während 12 # und # 13 Ursache des eigentlichen Matching.

Bewerben mit "global" und "dotall" Flaggen.

das Gegenteil (Spiel nur bedingte Kommentare) zu tun, wäre es so etwas wie diese:

<!(--)?(?=\[)(?:(?!<!\[endif\]\1>).)*<!\[endif\]\1>

Erklärung:

<!                  #01: "<!"
(--)?               #02: two dashes, optional
(?=\[)              #03: a position followed by "["
(?:                 #04: non-capturing group:
  (?!               #05:   a position not followed by
    <!\[endif\]\1>  #06:     "<![endif]>" or "<![endif]-->" (depends on #02)
  )                 #07:   end of look-ahead
  .                 #08:   eat the following char, it's part of the comment
)*                  #09: end of non-capturing group, repeat
<!\[endif\]\1>      #10: "<![endif]>" or "<![endif]-->" (depends on #02)

Auch hier gilt mit "global" und "dotall" Flaggen.

Schritt # 02 wegen der "Downlevel-enthüllt" Syntax finden Sie unter: . "MSDN - Über Conditional Comments"

Ich bin nicht ganz sicher, wo Räume erlaubt sind oder zu erwarten. In \s* zum Ausdruck, wo angemessen.

Andere Tipps

Wenn Sie nicht bekommen es mit einem regulären Ausdruck zu arbeiten, oder Sie finden Sie mehr Kommentare erhalten wollen Sie nutzen könnten preg_replace_callback . Sie können dann eine Funktion definieren, die Kommentare einzeln zu behandeln.

<?php
function callback($buffer) {
    return preg_replace_callback('/<!--.*-->/U', 'comment_replace_func', $buffer);
}

function comment_replace_func($m) {
    if (preg_match( '/^\<\!--\[if \!/i', $m[0])) {
        return $m[0];   
    }              

    return '';
}   

ob_start("callback");
?>

... HTML source goes here ...

<?php ob_end_flush(); ?>

Insgesamt scheint dies die beste Lösung zu sein:

<?php
  function callback($buffer) {
    return preg_replace('/<!--[^\[](.|\s)*?-->/', '', $buffer);
  }
  ob_start("callback");
?>
... HTML source goes here ...
<?php ob_end_flush(); ?>

Es entfernt alle Kommentare und verlässt conditionals mit Ausnahme der oben ein:

<!--[if !IE]><!-->
<link rel="stylesheet" href="/css/screen.css" type="text/css" media="screen" />
<!-- <![endif]-->

, wo die zusätzlichen scheint das Problem zu verursachen.

Wenn jemand die Regex vorschlagen, die dies berücksichtigen würden und dass condtional in Ort verlassen zu dann wäre das perfekt.

Tomalak Lösung sieht gut aus, aber als Neuling und keine weiteren Richtlinien, die ich weiß nicht, wie es zu implementieren, obwohl ich es versuchen möchte, wenn jemand erarbeiten kann, wie man es anwenden?

Danke

Ich bin mir nicht sicher, ob die PHP-Regex-Engine die folgende mögen, aber versuchen, dieses Muster:

'/<!--(.|\s)*(\[if .*\]){0}(.|\s)*?-->/'

So etwas wie dies funktionieren könnte:

/<!--[^\[](.|\s)*?-->/

Es ist das gleiche wie Sie, mit der Ausnahme, dass es ignoriert Kommentare eine öffnende Klammer haben unmittelbar nach dem Kommentar Starttag.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top