fboës - Der Blog

Pattern: Effizienter parsen

Um längere, kompliziert strukturierte Texte zu verändern, ist ein effizientes Parsen beim Programmieren eine wichtige Sache. Gerade bei HTML gibt es öfter den Wunsch, nur in bestimmten Bereichen eines längeren Textes Ersetzungen vorzunehmen.

So könnte die Aufgabe z.B. sein, innerhalb von HTML nur Anpassungen innerhalb einer <table>, eines <li> oder in <code> durchzuführen. Eine sehr performante Lösung dafür könnte ein Stream-Parser sein, der beim Erreichen eines bestimmten Zeichens in einen anderen Modus umspringt.

Tatsächlich lässt sich ein ähnliches Verhalten auch mittels einfacher Verschachtelung von regulären Ausdrücken erreichen. Das mag nicht so performant sein, ist aber eine größere Verbesserung gegenüber einer endlosen Aneinanderreihung von global durchgeführten, regulären Ersetzungen.

Ein Beispiel für ein solches Verhalten:

/**
 * Improves HTML.
 * @param  {String} html [description]
 * @return {String}      [description]
 */
var fixHtml = function (html) {
  return html
    // Fix in <table> 
    .replace(/(<table>)([\s\S]+?)(\/table)/g, function(all,before,content,after) {
      return
        before +
        content.replace(/(<tr>[\s]*)<td><strong>(.+?)<\/strong><\/td>/g,'$1<th scope="row">$2</th>') +
        after
      ;
    })
    // Fix in <code> 
    .replace(/(<code>)([\s\S]+?)(\/code)/g, function(all,before,content,after) {
      return
        before +
        content.replace(/((?:\/\/|\s#).+?(?:\n|$))/g, '<i class="comment">$1</i>') +
        after
      ;
    })
  ;
}