2013-03-01 7 views
3

J'ai une liste à plusieurs niveaux, par exemple ci-dessous:Liste HTML au format CSV

<ul>  
    <li>Test column 01 
     <ul>  
      <li>Test column 02 
       <ul>  
        <li>Test column 03 
         <ul>  
          <li>Test column 04 
           <ul>  
            <li>Test column 05</li> 
            <li>Test column 05</li> 
            <li>Test column 05</li> 
           </ul> 
          </li> 
         </ul> 
        </li> 
       </ul> 
      </li> 
     </ul> 
    </li> 
</ul> 

Je voudrais lancer un code php qui affiche la liste sous forme de fichier csv, formaté comme ci-dessous:

Test column 01 
,Test column 02 
,,Test column 03 
,,,Test column 04 
,,,,Test column 05 
,,,,Test column 05 
,,,,Test column 05 

Fondamentalement, je veux être en mesure d'exécuter une liste html, (avec un nombre illimité de niveaux), à travers un code php, et la sortie d'un fichier csv qui peut être ouvert dans Excel, en préservant les niveaux de liste dans les colonnes. Si je pouvais trouver un moyen d'ajouter une classe à chaque élément de la liste, en fonction de son niveau, les éléments de la liste de premier niveau obtiendraient une classe de niveau1, deuxième niveau, une classe de niveau2 etc etc, alors il devrait être assez simple à trouver et remplacer le reste.

Toute idée/aide grandement appréciée.

+0

Pour ajouter des classes est plus facile avec jQuery, si vous voulez analyser sur le côté serveur, vous devez parcourir la liste, garder un itérateur, lorsque vous trouvez un

    l'incrémenter, quand vous le trouvez
le décrémenter. Iterator sera le niveau (et combien de virgules vous avez). –

+0

avez-vous encore essayé quelque chose? Et pourquoi la colonne de test 5 comporte-t-elle trois rangées distinctes dans le CSV lorsque les valeurs sont dans le même UL? – Gordon

+0

Je pense que vous devriez parcourir votre liste et construire un tableau avec du texte et le niveau de profondeur, puis il est facile de faire le csv –

Répondre

1

Cela fonctionnerait pour votre exemple HTML:

$dom = new DOMDocument; 
$dom->preserveWhiteSpace = false; 
$dom->loadHTML($html); 

foreach ($dom->getElementsByTagName('li') as $li) { // #1 
    printf(
     '%s%s%s', 
     str_repeat(',', get_depth($li)),    // #2 
     trim($li->childNodes->item(0)->nodeValue),  // #3 
     PHP_EOL 
); 
} 

function get_depth(DOMElement $element) 
{ 
    $depth = -1; 
    while (           // #4 
     $element->parentNode->tagName === 'li' || 
     $element->parentNode->tagName === 'ul' 
    ) { 
     if ($element->parentNode->tagName === 'ul') { // #5 
      $depth++; 
     } 
     $element = $element->parentNode; 
    } 
    return $depth; 
} 

Vous pouvez see the demo here.

Explication des marques:

  1. Nous récupérons tous les éléments LI dans le balisage, quelle que soit leur position. Si vous souhaitez uniquement extraire un bloc UL particulier, utilisez getElementsByTagName à partir de DOMElement contenant l'élément UL de départ. Je laisse à vous de comprendre comment faire cela.
  2. nous ajoutons une virgule par profondeur calculée. La profondeur est égale à la quantité d'éléments UL au-dessus de l'élément LI actuel
  3. Nous ne récupérons que le premier nœud enfant de l'élément LI, en supposant que c'est le nœud de texte que vous voulez. Si votre balisage réel contient plus que le nœud de texte et les éléments UL potentiels, vous devez l'ajuster pour n'inclure que le contenu textuel souhaité. Nous coupons le résultat du texte pour supprimer les retours à la ligne qu'il aura quand il y aura des éléments UL fils dans l'élément LI.
  4. pour obtenir la profondeur que nous traversons l'arborescence DOM jusqu'à ce qu'il n'y ait plus d'élément LI ou UL.
  5. Puisque nous voulons une virgule par élément UL au-dessus du LI initial, on ajoute seulement +1 à la profondeur de $ si le parentNode est un élément UL
+0

Merci beaucoup pour ce @Gordon - c'est très apprécié. Je ne peux pas voir où je exporterais tout comme un fichier csv si ... – ss888

+0

@ ss888 il doesnt. Il les imprime seulement. Si vous le souhaitez dans un fichier, vous pouvez utiliser un SplFileObject ou, si vous ne voulez que le livrer au navigateur, envoyer un en-tête approprié. Les deux ont été couverts sur StackOverflow, donc je suis sûr que vous pourrez ajuster le code à vos besoins. – Gordon

+0

merci beaucoup, vous êtes une star! – ss888