Home » Php » php – Foreach loop group by XML element value

php – Foreach loop group by XML element value

Posted by: admin February 25, 2020 Leave a comment

Questions:

I want to group them by agent

XML structured as follows

<library>
    <document>
        <ProductName>somename1</ProductName>
        <productAgent>Agent-01</productAgent>
        <productType>Goods</productType>
    </document>
        <ProductName>somename3</ProductName>
        <productAgent>Agent-02</productAgent>
        <productType>Services</productType>
    </document>
    ......
</library>

Expecting Output

<ul>
    <li>Agent-01(productAgent)
        <ul>
            <li>somename1 - Goods</li>
        </ul>
    </li>
    <li>Agent-02(productAgent)
        <ul>
            <li>somename3 - Services</li>
            <li>somename6 - Goods</li>
        </ul>
    </li>
</ul>

What I tried

<ul>
    <li>Agent-01(productAgent)
        <ul>
            <?php foreach($xml->document as $item){     
                if ($item->productAgent == 'Agent-01' ) {
                    echo '<li>'.$item->ProductName.'-'.$item->ProductType.'</li>';
                }
            } 
            ?>
        </ul>
    </li>
    <li>Agent-02(productAgent)
        <ul>
            <?php foreach($xml->document as $item){     
                if ($item->productAgent == 'Agent-02' ) {
                    echo '<li>'.$item->ProductName.'-'.$item->ProductType.'</li>';
                }
            } 
            ?>
        </ul>
    </li>
</ul>

Problem

I have to modify my code every time the agent name change. My code doesn’t seem to be a good solution when the number of agent increase.

How to&Answers:

A more complete example with the output…

//  Build list of product names for each agent
$agents = [];
foreach ( $xml->document as $document ) {
    $agents [(string)$document->productAgent][] = (string)$document->ProductName;
}

?>
<ul>
    <?php // Loop over the agents
           foreach($agents as $name => $agent){  ?>
    <li><?php echo $name; ?>
        <ul>
            <?php // Loop over the the products for the agent
                  foreach($agent as $item){     
                echo '<li>'.$item.'</li>';
            } 
            ?>
        </ul>
    </li>
    <?php } ?>
</ul>

Answer:

Collect all data to array, where key is agent and value is array of products:

<?php 
$values = [];
foreach($xml->document as $item){     
    $agent = (string) $item->productAgent;
    if (!isset($values[$agent])) {
        $values[$agent] = [];
    }

    $values[$agent][] = (string) $item->ProductName;
    // add other tags as you need:
    //$values[$agent][] = [
    //    'name' => (string) $item->ProductName, 
    //    'type' => (string) $item->ProductType,
    //];
}

// Then iterate over this array and output as needed
foreach ($values as $agent => $products) {
    echo $agent . ': ' . implode(', ', $products);
    // iterate over $products and output what you need
}?>