Verschachtelte, hierarchische UL / LI-Listen auf eine Ebene reduzieren. Flatten hierarchical LI-lists to linear list.

Für ein web2print-Projekt, das verschachtelte HTML-Listen in Tags für InDesign umwandeln sollte, sind wir auf ein Problem gestossen: InDesign stellt verschachtelte Listen nicht wirklich durch verschachtelte Tag-Elemente dar, sondern man erstellt vorab für jede Hierarchie in der Bullet-Liste ein eigenes Absatzformat. Die Herausforderung lag also darin, aus dem HTML-Input per PHP ein XML-Output zu generieren, in dem die Tiefe der Listen-Verschachtelungen zu „flachen“ (flattened) Absatzformaten mit Kennzeichnung der Tiefe umgewandelt werden.

Ein Beispiel macht die Idee deutlich:
Aus einem HTML-Dokument mit einer klassischen, verschachtelten Liste…

Das ist eine Liste:
<ul>
   <li>Kapitel 1</li>
   <li>Kapitel 2
      <ul>
         <li>Kapitel 2.1</li>
         <li>Kapitel 2.2
            <ul>
               <li>Kapitel 2.2.1</li>
            </ul>
         </li>
      </ul>
   </li>
   <li>Kapitel 3</li>
</ul>
Viel Spass damit!

…sollte etwas in dieser Art generiert werden:

Das ist eine Liste:
<p class="depth-0">Kapitel 1</p>
<p class="depth-0">Kapitel 2</p>
<p class="depth-1">Kapitel 2.1</p>
<p class="depth-1">Kapitel 2.2</p>
<p class="depth-2">Kapitel 2.2.1</p>
<p class="depth-0">Kapitel 3</p>
Viel Spass damit!

Die Lösung setzt phpQuery.php ein – eine (geniale) Adaption der (noch genialeren) jQuery-Bibliothek für PHP statt JavaScript. Die Klasse mit entsprechender Rekursion dazu sah in PHP so aus:

<?php
require_once('phpQuery.php');
class renderEngine {
 
function flatten_nested_lists ( $txt ) {
$nodes = phpQuery::newDocument( $txt );
$this->flatten_nested_lists_recursion( $nodes );
return $nodes->html();
}
 
function flatten_nested_lists_recursion ( $el, $depth = 0) {
$arr = [];
foreach ($el->children('ul') as $cnt_ul=>$ul) {
$ul = pq($ul);
$arr = [];
foreach ($ul->children('li') as $cnt_li=>$li) {
$li = pq($li);
$li->attr('depth', $depth);
$liClone = $li->clone();
$liClone->find('ul')->remove();
$str = trim($liClone->attr('depth').' - '.$liClone->html());
$arr[] = '<p aid:pstyle="Bullet_Lv_'.$liClone->attr('depth').'">'.$str.'</p>';
$arr = array_merge($arr, $this->flatten_nested_lists_recursion($li, $depth+1));
}
foreach ($arr as $n) {
$ul->before($n);
}
$ul->remove();
}
$el->children('ul')->remove();
return $arr;
}
}

…und in Funktion dann so:

 
$Engine = new renderEngine();
$input = '...hier der HTML-Code mit ul/li rein...';
echo $Engine->flatten_nested_lists($input);

36 thoughts to “Verschachtelte, hierarchische UL / LI-Listen auf eine Ebene reduzieren. Flatten hierarchical LI-lists to linear list.”

  1. Lose up to 23 pounds of pure body fat in just 3 weeks!, how did i do that?
    The 3 Week Diet is an extreme rapid weight loss program that can help you lose up to 23 pounds of pure body fat in just 3 weeks! Get your customized diet plan from our official website and find out which foods you should be eating if you want to burn your belly fat away fast! Created by acclaimed personal trainer and nutritionist Brian Flatt, The 3 Week Diet is 100% guaranteed to deliver results!
    look great? dont waste your time! lets do this, join with us and bet back your beautiful body at here:

    http://polr.me/1f0e
    Thx

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.