简体   繁体   中英

Counting items in each category - php loop on xml categorized list

I have a new problem in xml looping on xml nodes, where each group of items are wrapped with category node, what i want to do is:
1- get randomly 3 items from any of the categories "randomly".
2- get the parent of each of the selected items.

my XML sample and php are in the below eval or as written below: https://eval.in/544360

<?php
$x = <<<XML
<?xml version="1.0" encoding="utf-8"?>
<List>
<category name="cat1" dispName="First Category" catCode="FC1">
    <item itmCode="item1" show="true">
        <name>item 1</name>
        <img>path to image 1</img>
    </item>
    <item itmCode="item2">
        <name>item 2</name>
        <img>path to image 2</img>
    </item>
</category>
<category name="cat2" dispName="Second Category" catCode="SC2">
    <item itmCode="item21">
        <name>item 21</name>
        <img>path to image 21</img>
    </item>
    <item itmCode="item22">
        <name>item 22</name>
        <img>path to image 22</img>
    </item>
    <item itmCode="item54">
        <name>item 54</name>
        <img>path to image 54</img>
    </item>
    <item itmCode="item99">
        <name>item 99</name>
        <img>path to image 99</img>
    </item>
</category>
</List>
XML;

$xml = simplexml_load_string($x); // assume XML in $x
$itemCount=0;
foreach($xml->category->item as $item){
  $itemCount++;
}
echo $itemCount;?>

Thanks a lot for any help and support

You are iterating the first <category> only, it has two <item> nodes.
To accomplish your outcomes, I suggest to...

  • use xpath() to get an array $items of all <item> nodes in your XML.
  • randomize $items with shuffle()
  • iterate over $items array and echo each <item>
  • use xpath() again to get the <item> 's parent and echo its name -attribute
  • break the loop after 3 iterations

sample code:

$xml = simplexml_load_string($x); // assume XML in $x
$items = $xml->xpath("/List/category/item");
shuffle($items);

$count = 0;
foreach ($items as $item) {
    echo $item->name . " from category ";
    echo $item->xpath("../@name")[0] . PHP_EOL;

    $count++;
    if ($count >= 3) break;    
} 

see it in action: https://eval.in/545896

Comments:

  • xpath() returns an array of SimpleXml -elements, that's why each $item can be treated as an object ( echo $item->name; ).
  • and xpath() can be used again to retrieve the parent ( .. ) and its attribute ( ../@name ); note that @ for attribute.
  • because xpath() returns an array, it needs to be de-referenced with [0] (2nd echo ).

Update:

On PHP < 5.4 you should update, and if this is not possible, de-reference like this:

$parents = $item->xpath('../@name'); 
echo $parents[0] . PHP_EOL;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM