Chris Armstrong
Chris Armstrong

Reputation: 3625

Parse XML to a nested list with PHP

I have an XML file which contains family tree data in a nested structure, and I'm wanting to parse it into a nested list.

I have the following code

<?php 
    $doc = new DOMDocument();
    $doc->load('armstrong.xml');
    echo $doc->saveXML();
?>

Which loads in the following XML file and prints it as-is

<?xml version="1.0" encoding="UTF-8"?>
<indi>
    <id>id1</id>
    <fn>Matt</fn>
    <bday>1919</bday>
    <dday>2000</dday>
    <spouse>Evelyn Ross</spouse>
    <family>
        <indi>
        <id>id2</id>
        <fn>Jane</fn>
        <bday></bday>
        <dday></dday>
        <spouse></spouse>
        <family>

        </family>
    </indi>
    <indi>
        <id>id3</id>
        <fn>Jason</fn>
        <bday></bday>
        <dday></dday>
        <spouse></spouse>
        <family>

        </family>
    </indi>
    <indi>
        <id>id4</id>
        <fn>Samuel</fn>
        <bday></bday>
        <dday></dday>
        <spouse></spouse>
        <family>
            <indi>
                <id>id5</id>
                <fn>John</fn>
                <bday></bday>
                <dday></dday>
                <spouse></spouse>
                <family>

                </family>
            </indi>
            <indi>
                <id>id6</id>
                <fn>John</fn>
                <bday></bday>
                <dday></dday>
                <spouse></spouse>
                <family>

                </family>
            </indi>
        </family>
    </indi>
</family>

However I want to parse it into the following format:

<ul>
   <li> 
    <span class="vcard person" id="id1">
            <span class="edit fn">Matt</span> 
        <span class="edit bday">1956</span> 
        <span class="edit dday"></span>
            <span class="edit spouse">Eunace Fulton</span>
        </span> 
    <ul> ... List of Family ... </ul>
   </li>
</ul>

I'm pretty new to php, so if this is an incredibly simple problem I apologise! Would really appreciate any ideas.

EDIT

I'm now using the following recursive loop but still having problems

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

    function outputIndi($indi) {
        $i = new DOMDocument();
        $i = $indi;

        echo '<li>';

        echo '<span class="edit fn">' . $indi->getElementsByTagName("fn") . '</span>'; // name not a real attribute, must access through DOM
        echo '<span class="edit bday">' . $indi->getElementsByTagName("bday") . '</span>'; // ditto
        // ...

        echo '<ul>';
        foreach ($indi->getElementsByTagName("family") as $subIndi) { // again, family not a real attribute
            outputIndi($subIndi);
        }
        echo '</ul>';

        echo '</li>';
    }

    outputIndi($doc->documentRoot);

    ?>

Upvotes: 1

Views: 2500

Answers (1)

Jonah
Jonah

Reputation: 10091

Here's your code. You'll need to add the rest of the attributes (dday, spouse)

RECURSION!

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 '<ul>';
    $family = $indi->getElementsByTagName('family')->item(0)->childNodes;
    foreach ($family as $subIndi) {
        outputIndi($subIndi);
    }
    echo '</ul>';
    echo '</span>';
    echo '</li>';
}

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

outputIndi($doc->documentElement);

You see, it outputs all information about an "indi", loops through each child of <family>, and calls itself on that. Does that make sense?

Upvotes: 1

Related Questions