2008-11-25 2 views
2

PHP로 데이터를 사용하여 계층 적 태그 세트를 어떻게 구축합니까? 예를 들어PHP의 계층 적 HTML 태그를 플랫 데이터로 구축

, 중첩 된 목록 :

<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) 

가 멋지게 예를 들어 같은 형식한다면 그것은 좋은 것 너무.

+0

계층 구조를 만들기 위해 배열에 충분한 데이터가 없습니다. 스크립트는 "하위 모음"항목을 ​​"막대"에 첨부하는 것을 어떻게 알 수 있습니까? 네가 다른 둥지를 틀면 "서브 서브 바"가 될까? 깊이 값은 쓸모가 없습니다. 배열을 계층 적으로 만들지 않는 이유는 무엇입니까? –

+0

배열의 순서가 중요합니다. 트릭은 깊이 정보가있는 플랫 데이터에서 계층 구조를 작성합니다. 이 제목을 더 명확하게 편집 할 것입니다. – postfuturist

+0

자, 하위 항목이 각각의 부모에게 올바르게 부착되도록하기위한 규칙은 무엇입니까? 색인 순서? 명명 규칙? –

답변

2

편집 :

은 이미 코멘트 말했다 서식 추가 데이터 구조는 다소 이상합니다. 텍스트 조작 (예 : 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"; 
    } 

} 
0

당신은

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

같은 것이 하위 목록에 대한 설명으로 시작하지 않으면 내가 아는

<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> 

이 약간의 차이를 프로그래머 생산 의미한다.

개인적으로 나는 보통 PHP로 작업하기가 쉬운 한 HTML이 어떻게 보이는지 상관하지 않습니다.

편집 : 당신이 첫 번째 통해 실행하면 OK, 작동 ... : 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); 
+0

이것은 계층 적으로 중첩 된 배열을위한 솔루션처럼 보입니다. 좋은 해결책이지만 내 문제는 아닙니다. – postfuturist

0

을 내가 코멘트 필드에 너무 정교 질문에 대해 질문이 있습니다.

어떻게 속성 데이터에 적합합니까? 즉 정확하게 프로그래밍 방식으로 HTML 데이터 집합을 표현하기 위해 필요한 최소한의 구조이기 때문에, 당신은

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') 
     )) 
     )) 
    )) 
    )) 
)) 
)); 

같은 Whory 표 ™ 필요 했어.

나는

배열 (이름, 속성, 어린이)

대신 문자열이있는 경우 가정함으로써, 아주 많이 "텍스트 노드"요소에 대한 필요성을 제거함으로써 약간의 속임수를했습니다 'children'배열의 암시 적 텍스트 노드 인 과 name == null 인 노드는 태그가 없으므로 텍스트 노드이기도합니다. 나는 당신이 원하는 무슨 생각

당신의 인생을 쉽게

FWIW를 만들기 위해 나무에 일부 기존의 HTML을 구문 분석하는 적절한 프로그램 DOM 생성 도구입니다, 위의 구조는 오히려 쉽게 HTML로 직렬화 할 수 있습니다.

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; 
} 
+0

whory table? 맨 페이지주세요 :) – Ken