Danny
Danny

Reputation: 1

Parsing multiple nested elements as an unordered list with SimpleXML using PHP foreach

I'm working with an XML product list that displays a list of around 20 products, and within each <item> there is a <description> and then one <bullet> for each. Here's an example:

XML File with <bullet> List

I'm using a foreach loop with SimpleXML to pull in the product data, and all individual tags such as <image> and <title> are working fine.

My issue is that it is only parsing the first <bullet> for each product and not all of them. To fix this I attempted to add a for loop which targets all nested items within the <description> tag and outputs however many there are. But it's now giving me the first <bullet> of the first item on the XML file and putting it under every product, instead of showing multiple bullets for each respective product, which is what I want.

I'll post my script and hopefully someone will be able to point out where I'm going wrong.

<?php
$items = simplexml_load_file('http://www.itclear.com/BestSellers.xml');

foreach ($items->channel->item as $item):
    $title=$item->title;
    $image=$item->image;
    $price=$item->price;
    $description=$item->description;
    $link=$item->link;

    echo '
             <div class="xsmall-12 medium-6 large-4 columns product">
                <div class="inner">
                    <div class="product-image">
                        <img class="product-image" src="',$image,'"/>
                    </div>
                <h2 class="product-title"><strong>',$title,'</strong></h2>

                <ul>';

    $bullets = $items->channel->item->description;
    for($i=0;$i<=$bullets;$i++){
        echo '<li>',$bullets[$i]->bullet,'</li>';
    }

    echo'
               </ul><span class="product-price">&pound;',$price,'</span>
                <a class="product-link" href="',$link,'" target="_blank" title="Visit ITC Sales to buy ',$title,'">View Deal <i class="fa fa-angle-right" aria-hidden="true"></i></a>
             </div>
         </div>';
    endforeach;

?>

Rendered HTML & CSS

Upvotes: 0

Views: 240

Answers (2)

Danny
Danny

Reputation: 1

I also found an alternative solution to this for those also stuck with a similar problem. Here's the code:

    <?php

        $xml = 'http://www.itclear.com/BestSellers.xml';

        $items = simplexml_load_file($xml);

        foreach ($items->channel->item as $item) {

            $title = $item->title;
            $image=$item->image;
            $price=$item->price;
            $description=$item->description;
            $link=$item->link;

            echo '
             <div class="xsmall-12 medium-6 large-4 columns product">
                <div class="inner">
                    <div class="product-image">
                        <img class="product-image" src="',$image,'"/>
                    </div>
                <h2 class="product-title"><strong>',$title,'</strong></h2>

                <ul class="product-description">';

            foreach ($item->description->bullet as $bullet) {
                echo '<li>';
                $b = $bullet;
                echo $b;
                echo "</li>";

            }


            echo'
               </ul><span class="product-price">&pound;',$price,'</span>
                <a class="product-link" href="',$link,'" target="_blank" title="Visit ITC Sales to buy ',$title,'">View Deal <i class="fa fa-angle-right" aria-hidden="true"></i></a>
             </div>
         </div>';

        }

    ?>

Upvotes: 0

IMSoP
IMSoP

Reputation: 97718

Your problem is with this line:

$bullets = $items->channel->item->description;

This line has no mention of the elements you're looping over in the outer foreach loop, so has no way to know which item you want to look at. It just says "look at the first <channel> in the document, then look at the first <item> in that, then look at the <description> elements in that".

What you want is to use the $item variable defined in your loop, and look at the <description> elements there:

$bullets = $item->description;

But this variable name is not quite right - the $bullets variable now holds one or more <description> elements, not the <bullet> elements under it. So we should instead say:

$description = $item->description;
$bullets = $description->bullet;

Note that we don't now need $bullets[$i]->bullet, because $bullets[$i] should already be the <bullet> element; you also need to count() the bullets, which is missing in your code. So we have:

for($i=0;$i<=count($bullets);$i++){
    echo '<li>',$bullets[$i],'</li>';
}

To simplify all this, you can just use the same style of foreach loop you already have at the top of the file:

foreach ( $item->description->bullet as $bullet ) {
    echo '<li>',$bullet,'</li>';
}

Upvotes: 1

Related Questions