Düz verilerden PHP hiyerarşik html etiketleri inşa

3 Cevap php

Nasıl PHP verilerle etiketleri hiyerarşik bir dizi yaratırım?

Örneğin, iç içe geçmiş bir listesi:

<div>
    <ul>
        <li>foo
        </li>
        <li>bar
            <ul>
                <li>sub-bar
                </li>
            </ul>
        </li>
    </ul>
</div>

Bu, bu gibi düz verilerden inşa olacaktır:

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)

Bu güzel örnekte olduğu gibi biçimlendirilmiş olsaydı çok güzel olurdu.

3 Cevap

Edit: Added formatting

Zaten yorum dedi, veri yapısı biraz garip. Bunun yerine (OIS) gibi metin manipülasyon kullanarak, ben DOM tercihim:

<?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();

Sizin biçimlendirme kongre tür garip. Bunu başarmak için aşağıdaki ile son satırı değiştirin:

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";
    }

}

Ben yorum alanı için çok ayrıntılı bir soru ile ilgili bir sorum var.

O öznitelik veri sığdırmak için nasıl istiyorsun? Bir Whory Tablo gerekiyordu ™ gibi

array('html', null, array (
  array( 'div' , null , array( 
    array('ul', array('id'=>'foo'), array( 
      array('li', null, 'foo' ),
        array('li', null, array( 
          array(null,null, 'bar'), 
          array('ul', null, array( 
            array('li', null, 'sub-bar' )
          ))
        ))
      ))
    ))
  ))
));

Bu doğru programlı bir HTML veri kümesi temsil etmek için gerekli minimum yapıdır çünkü.

Ben varsayım eğer yaparak, oldukça çok "text-düğümü" elemanları için ihtiyacı ortadan kaldırarak biraz aldattım

array (isim, nitelik, çocuk)

has a string instead of an array for 'children' then its an implicit text-node, and that nodes with name == null are dont have tags and are thus also text nodes.

Ne istediğiniz düşünüyorum hayatınızı kolaylaştırmak için bir ağaca varolan bazı html ayrıştırmak olacak uygun bir programatik DOM üretme aracı

FWIW, yukarıda yapısı oldukça kolay html içine serileştirilebilir.

function tohtml( $domtree ){ 
   if( is_null($domtree[0]) ){ 
     if( !is_array($domtree[2])){ 
         return htmlentities($domtree[2]);
     }
     die("text node cant have children!"); 
   }
   $html = "<" . $domtree[0]; 
   if( !is_null( $domtree[1] ) )
   {
     foreach( $domtree[1] as $name=>$value ){ 
       $html .= " " . $name . '="' . htmlentities($value) . '"'; 
     }
   }
   $html .= ">" ; 
   if( !is_null($domtree[2]) ){
     if( is_array($dometree[2]) ){ 
        foreach( $domtree[2] as $id => $item ){ 
          $html .= tohtml( $item ); # RECURSION
        } 
     }
     else {
       $html .= htmlentities($domtree[2]);
     }
  }
  $html .= "</" . $domtree[1] . ">"; 
  return $html; 
}

Sen gibi bir şey demek

function array_to_list(array $array, $width = 3, $type = 'ul', $separator = ' ', $depth = 0)
{
    $ulSpace = str_repeat($separator, $width * $depth++);
    $liSpace = str_repeat($separator, $width * $depth++);
    $subSpace = str_repeat($separator, $width * $depth);
    foreach ($array as $key=>$value) {
        if (is_array($value)) {
        $output[(isset($prev) ? $prev : $key)] .= "\n" . array_to_list($value, $width, $type, $separator, $depth);
        } else {
            $output[$key] = $value;
            $prev = $key;
        }
    }
    return "$ulSpace<$type>\n$liSpace<li>\n$subSpace" . implode("\n$liSpace</li>\n$liSpace<li>\n$subSpace", $output) . "\n$liSpace</li>\n$ulSpace</$type>";
}

echo array_to_list(array('gg', 'dsf', array(array('uhu'), 'df', array('sdf')), 'sdfsd', 'sdfd')) . "\n";

üretir

<ul>
   <li>
      gg
   </li>
   <li>
      dsf
      <ul>
         <li>

            <ul>
               <li>
                  uhu
               </li>
            </ul>
         </li>
         <li>
            df
            <ul>
               <li>
                  sdf
               </li>
            </ul>
         </li>
      </ul>
   </li>
   <li>
      sdfsd
   </li>
   <li>
      sdfd
   </li>
</ul>

Ben bir alt liste bir açıklama ile başlamak yoksa orada küçük bir boşluk gidecekseniz biliyorum.

Şahsen ben genellikle gerçekten HTML sürece PHP ile çalışmak kolay gibi görünüyor nasıl umurumda değil.

Düzenleme: Bu ilk aracılığıyla çalıştırırsanız Tamam, çalışır ...: P

function flat_array_to_hierarchical_array(array &$array, $depth = 0, $name = null, $toDepth = 0)
{
    if ($depth == 0) {
        $temp = $array;
        $array = array_values($array);
    }
    if (($name !== null) && ($depth == $toDepth)) {
        $output[] = $name;
    } else if ($depth < $toDepth) {
        $output[] = flat_array_to_hierarchical_array(&$array, $depth + 1, $name, $toDepth);
    }
    while ($item = array_shift($array)) {
        $newDepth = $item['depth'];
        $name = $item['name'];
        if ($depth == $newDepth) {
            $output[] = $name;
        } else if ($depth < $newDepth) {
            $output[] = flat_array_to_hierarchical_array(&$array, $depth + 1, $name, $newDepth);
        } else {
            array_unshift($array, $item);
            return $output;
        }
    }
    $array = $temp;
    return $output;
}

$arr = flat_array_to_hierarchical_array($nested_array);
echo array_to_list($arr);