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:
- Kapitel 1
- Kapitel 2
- Kapitel 2.1
- Kapitel 2.2
- Kapitel 2.2.1
- Kapitel 3
…sollte etwas in dieser Art generiert werden:
Das ist eine Liste:
Kapitel 1
Kapitel 2
Kapitel 2.1
Kapitel 2.2
Kapitel 2.2.1
Kapitel 3
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:
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[] = ''.$str.'
';
$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);