SitePoint Sponsor

User Tag List

Results 1 to 3 of 3
  1. #1
    SitePoint Evangelist Muller2's Avatar
    Join Date
    Feb 2005
    Location
    Oxford, UK
    Posts
    522
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    xml child/parent help

    Hi,

    I have been trying to build a child/parent navigation for a little while now using PHP (I'm from a .net background) and I can't get close to the desired results. I am loading my data from an xml file using simplexml successfully but I am trying to workout how I can map that into arrays or variables so I can write it out.

    The xml is
    Code:
      <Categories>
      <Category>
        <ID>1</ID>
        <Title>Days</Title>
        <Description />
        <ParentID />
        <Meta />
      </Category>
      <Category>
        <ID>2</ID>
        <Title>Monday</Title>
        <Description />
        <ParentID>1</ParentID>
        <Meta />
      </Category>
      <Category>
        <ID>3</ID>
        <Title>Tuesday</Title>
        <Description />
        <ParentID>1</ParentID>
        <Meta />
      </Category>
      <Category>
        <ID>4</ID>
        <Title>Wednesday</Title>
        <Description />
        <ParentID>1</ParentID>
        <Meta />
      </Category>
      <Category>
        <ID>5</ID>
        <Title>Thursday</Title>
        <Description />
        <ParentID>1</ParentID>
        <Meta />
      </Category>
      <Category>
        <ID>6</ID>
        <Title>Friday</Title>
        <Description />
        <ParentID>1</ParentID>
        <Meta />
      </Category>
      <Category>
        <ID>7</ID>
        <Title>Saturday</Title>
        <Description />
        <ParentID/>
        <Meta />
      </Category>
      <Category>
        <ID>8</ID>
        <Title>Sunday</Title>
        <Description />
        <ParentID/>
        <Meta />
      </Category>
    </Categories>
    Now my PHP
    PHP Code:
    foreach($categories as $category) {

                    if (
    $category->ParentID != "")
                    {
                        echo 
    "<li><a href=index.php?Cat=$category->ID>$category->Title</a></li>";
                        echo 
    "<ul>";
                        foreach(
    $categories as $subcategory) {
                        if (
    $subcategory->ParentID == $category->ID)
                        {
                            echo 
    "<li><a href=index.php?Cat=$subcategory->ID>$subcategory->Title</a></li>";
                        }
                        }
                        echo 
    "</ul>";
                    }
                    else
                    {
                        echo 
    "<li><a href=index.php?Cat=$category->ID>$category->Title</a></li>";
                    } 
                } 
                echo 
    "</ul>"
    So my desired output would be something like this:
    HTML Code:
    <ul id="p7menubar">
    <li><a class="trigger" href="#">Days</a>
    <ul>
    <li><a href="#">Monday</a></li>
    <li><a href="#">Tuesday</a></li>
    <li><a href="#">Wednesday</a></li>
    <li><a href="#">Thursday</a></li>
    <li><a href="#">Friday</a></li>
    </ul>
    </li>
    <li><a href="index.htm">Saturday</a></li>
    <li><a href="index.htm">Sunday</a></li>
    </ul>

    If anyone could help me out it would be very much appreciated

    Thanks

    Al

  2. #2
    SitePoint Member
    Join Date
    Jun 2006
    Location
    Chicago or Urbana/Champaign, depending
    Posts
    14
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you run print_r on the SimpleXML object, you'd get something like this:

    Code:
    SimpleXMLElement Object
    (
        [Category] => Array
            (
                [0] => SimpleXMLElement Object
                    (
                        [ID] => 1
                        [Title] => Days
                        [Description] => SimpleXMLElement Object
                            (
                            )
    
                        [ParentID] => SimpleXMLElement Object
                            (
                            )
    
                        [Meta] => SimpleXMLElement Object
                            (
                            )
    
                    )
    
                [1] => SimpleXMLElement Object
                    (
                        [ID] => 2
                        [Title] => Monday
                        [Description] => SimpleXMLElement Object
                            (
                            )
    
                        [ParentID] => 1
                        [Meta] => SimpleXMLElement Object
                            (
                            )
    
                    )
    
                [2] => SimpleXMLElement Object
                    (
                        [ID] => 3
                        [Title] => Tuesday
                        [Description] => SimpleXMLElement Object
                            (
                            )
    
                        [ParentID] => 1
                        [Meta] => SimpleXMLElement Object
                            (
                            )
    
                    )
    ...
    What you're doing is trying to find the parent categories by testing to see if $category->ParentID does not equal "" (a blank string). But the problem is in the parent categories, $category->ParentID does equal "". So if you change it to if ($category->ParentID == ""), then it would work.

    Another problem with your code is that you don't test to see if a parent category has children before you echo out the <ul> tags. Also, looping through the same array with foreach so many times is inefficient. A much cleaner solution would be to first organize the the XML into parents and children:

    PHP Code:
    $parents = array();
    $children = array();

    foreach (
    $categories as $category) {
        
    // this is a parent category
        
    if ($category->ParentID == "") {
            
    // without the (int) and (string) typecasts, $category->ID and $category->Title would be
            // SimpleXMLElement Objects instead of ints and strings, like we want them to be
            
    $parents[(int) $category->ID] = (string) $category->Title;
        
    // and this is a child category
        
    } else {
            
    $children[(int) $category->ParentID][(int) $category->ID] = (string) $category->Title;
        }
    }

    /* Based on the sample XML you provided, $parents would look like this:
    Array
    (
        [1] => Days
        [7] => Saturday
        [8] => Sunday
    )

    and $children would look like this:
    Array
    (
        [1] => Array
            (
                [2] => Monday
                [3] => Tuesday
                [4] => Wednesday
                [5] => Thursday
                [6] => Friday
            )

    )
    */ 
    and then once you have the XML neatly sorted like that, it'd be very easy to create the list that you wanted:

    PHP Code:
    // now we loop through all the parents
    foreach ($parents as $id => $title) {
        
    // output them
        
    echo "<li><a href=index.php?Cat=$id>$title</a></li>";

        
    // and if they have any children, then create a list for all the children
        
    if (isset($children[$id])) {
            echo 
    "<ul>";

            foreach(
    $children[$id] as $subID => $subTitle) {
                echo 
    "<li><a href=index.php?Cat=$subID>$subTitle</a></li>";
            }

            echo 
    "</ul>";
        }


  3. #3
    SitePoint Evangelist Muller2's Avatar
    Join Date
    Feb 2005
    Location
    Oxford, UK
    Posts
    522
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thank you bcafs7!

    I can't thank you enough that works perfectly


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •