如何在PHP中用数据构建一组分层的标记?
例如,嵌套列表:
<div>
<ul>
<li>foo
</li>
<li>bar
<ul>
<li>sub-bar
</li>
</ul>
</li>
</ul>
</div>
这将基于如下平面数据构建:
nested_array = array();
nested_array[0] = array('name' => 'foo', 'depth' => 0)
nested_array[1] = array('name' => 'bar', 'depth' => 0)
nested_array[2] = array('name' => 'sub-bar', 'depth' => 1)
如果它的格式也能像示例一样好,那就太好了。
最佳答案
编辑:添加的格式
正如评论中已经提到的,您的数据结构有些奇怪。与使用文本操作(如OIS)不同,我更喜欢DOM:
<?php
$nested_array = array();
$nested_array[] = array('name' => 'foo', 'depth' => 0);
$nested_array[] = array('name' => 'bar', 'depth' => 0);
$nested_array[] = array('name' => 'sub-bar', 'depth' => 1);
$nested_array[] = array('name' => 'sub-sub-bar', 'depth' => 2);
$nested_array[] = array('name' => 'sub-bar2', 'depth' => 1);
$nested_array[] = array('name' => 'sub-sub-bar3', 'depth' => 3);
$nested_array[] = array('name' => 'sub-sub3', 'depth' => 2);
$nested_array[] = array('name' => 'baz', 'depth' => 0);
$doc = new DOMDocument('1.0', 'iso-8859-1');
$doc->formatOutput = true;
$rootNode = $doc->createElement('div');
$doc->appendChild($rootNode);
$rootList = $doc->createElement('ul');
$rootNode->appendChild($rootList);
$listStack = array($rootList); // Stack of created XML list elements
$depth = 0; // Current depth
foreach ($nested_array as $nael) {
while ($depth < $nael['depth']) {
// New list element
if ($listStack[$depth]->lastChild == null) {
// More than one level at once
$li = $doc->createElement('li');
$listStack[$depth]->appendChild($li);
}
$listEl = $doc->createElement('ul');
$listStack[$depth]->lastChild->appendChild($listEl);
array_push($listStack, $listEl);
$depth++;
}
while ($depth > $nael['depth']) {
array_pop($listStack);
$depth--;
}
// Add the element itself
$li = $doc->createElement('li');
$li->appendChild($doc->createTextNode($nael['name']));
$listStack[$depth]->appendChild($li);
}
echo $doc->saveXML();
你的格式惯例有点奇怪。将最后一行替换为以下内容:
printEl($rootNode);
function printEl(DOMElement $el, $depth = 0) {
$leftFiller = str_repeat("\t", $depth);
$name = preg_replace('/[^a-zA-Z]/', '', $el->tagName);
if ($el->childNodes->length == 0) {
// Empty node
echo $leftFiller . '<' . $name . "/>\n";
} else {
echo $leftFiller . '<' . $name . ">";
$printedNL = false;
for ($i = 0;$i < $el->childNodes->length;$i++) {
$c = $el->childNodes->item($i);
if ($c instanceof DOMText) {
echo htmlspecialchars($c->wholeText);
} elseif ($c instanceof DOMElement) {
if (!$printedNL) {
$printedNL = true;
echo "\n";
}
printEl($c, $depth+1);
}
}
if (!$printedNL) {
$printedNL = true;
echo "\n";
}
echo $leftFiller . '</' . $name . ">\n";
}
}