Почему мой рекурсивный цикл создает слишком много детей? - PullRequest
0 голосов
/ 11 декабря 2010

Я использую рекурсивный цикл PHP для анализа XML-документа, чтобы создать вложенный список, однако по какой-то причине цикл прерывается и создается дубликаты элементов в списке, а также пустых элементов.

XML (список данных генеалогического дерева) структурирован следующим образом:

        <?xml version="1.0" encoding="UTF-8"?>
<family>
<indi>
    <id>id1</id>
    <fn>Thomas</fn>
    <bday></bday>
    <dday></dday>
    <spouse></spouse>
    <family>
            <indi>
                   <id>id1</id>
                   <fn>Alexander</fn>
                   <bday></bday>
                   <dday></dday>
                   <spouse></spouse>
                  <family>
                  </family>
           </indi>
           <indi>
                   <id>id1</id>
                   <fn>John</fn>
                   <bday></bday>
                   <dday></dday>
                   <spouse></spouse>
                   <family>
                            <indi>
                                 <id>id1</id>
                                 <fn>George</fn>
                                 <bday></bday>
                                 <dday></dday>
                                 <spouse></spouse>
                                 <family>
                                 </family>
            </indi>
                   </family>
            </indi>
    </family>
</indi>
</family>

А вот мой цикл PHP, который загружает файл XML, затем перебирает его, чтобы создать вложенный ul:

<?php 
    function outputIndi($indi) {
        echo '<li>';
        $id = $indi->getElementsByTagName('id')->item(0)->nodeValue;
        echo '<span class="vcard person" id="' . $id . '">';

        $fn = $indi->getElementsByTagName('fn')->item(0)->nodeValue;
        $bday = $indi->getElementsByTagName('bday')->item(0)->nodeValue;

        echo '<span class="edit fn">' . $fn . '</span>';
        echo '<span class="edit bday">' . $bday . '</span>';
        // ...
        echo '</span>';
        echo '<ul>';
        $family = $indi->getElementsByTagName('family');
        foreach ($family as $subIndi) {
                outputIndi($subIndi);
            }
        echo '</ul></li>';
    }

    $doc = new DOMDocument();
    $doc->load('armstrong.xml');

    outputIndi($doc);

    ?>

РЕДАКТИРОВАТЬ вот желаемый результат (вложенные списки, со знаковыми семьями ul и знаковыми личностями li)

<ul>
  <li>
    <span class="vcard">
      <span class="fn">Thomas</span>
      <span class="bday"></span>
      <span class="dday"></span>
      <ul>
             ... repeat for all ancestors ...
      </ul>
   <li>
<ul>

Вы можете увидеть результат в http://chris -armstrong.com / gortin .Есть идеи, где я иду не так?Я думаю, что это как-то связано со значением $ subIndi, но каждый раз, когда я пытаюсь изменить его, я получаю сообщение об ошибке.Буду очень признателен за любую помощь!

Ответы [ 3 ]

3 голосов
/ 13 декабря 2010

Звучит идеально! Не могли бы вы дать мне пример? Значит ли это, что я могу спасти данные как XML, а затем загрузить их как вложенные уль-х?

Да, вы можете сделать именно это. Вот XSL, который отображает вложенные UL:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
      <html>
      <body>
        <h2>Family tree</h2>
        <ul>
            <li><xsl:value-of select="indi/fn" /></li>

            <!-- apply-templates will select all the indi/family nodes -->
            <xsl:apply-templates select="indi/family" />
        </ul>
      </body>
      </html>
    </xsl:template>

    <xsl:template match="family">       
        <ul>
            <li>
                <div>
                    <xsl:value-of select="id" />: <xsl:value-of select="fn" />
                    (<xsl:variable name="bday" select="bday" />
                    to
                    <xsl:variable name="dday" select="dday" />)
                </div>
            </li>
            <!-- This node matches the 'family' nodes, and we're going to apply-templates on the inner 'family' node,
            so this is the same thing as recursion. -->
            <xsl:apply-templates select="family" />
        </ul>
    </xsl:template>
</xsl:stylesheet>

Я не знаю php, но эта статья покажет вам, как преобразовать XML с помощью таблицы стилей выше.

Вы также можете связать свою таблицу стилей, добавив директиву таблицы стилей вверху вашего XML-файла (см. для примера ).

0 голосов
/ 12 декабря 2010

Заменить

$family = $indi->getElementsByTagName('family');
foreach ($family as $subIndi) {
        outputIndi($subIndi);
    }

этим

if(!empty($indi))
foreach($indi as $subIndi){  
     outputIndi($subIndi);
} 

Я понимаю,
если ($ показываемое> hasChildNodes ()) лучше чем
if (! empty ($ indi))

0 голосов
/ 11 декабря 2010

getElementsByTagName предоставит вам все узлы, а не только непосредственные дочерние элементы:

$family = $indi->getElementsByTagName('family');
foreach ($family as $subIndi) {
    outputIndi($subIndi);
}

Вы будете вызывать outputIndi () для внуков и т. Д.

Здесьпример (из другого вопроса stackoverflow ):

for ($n = $indi->firstChild; $n !== null; $n = $n->nextSibling) {
    if ($n instanceof DOMElement && $n->tagName == "family") {
        outputIndi($n);
    }
}
...