The problem that you get only one item is that you fetch only one item.
This might sound a bit moot, point in case is, that you're putting the parent element into $item
which actually is there only once.
So you're not stepping deep enough. Step one more deep to iterate over the correct children and it works like you planned it:
$xml = simplexml_load_file($path_to_xml_file);
$ns = $xml->getDocNamespaces();
$data = $xml->children($ns['rsp']);
$list = $data->children($ns['lStk']); // first the list
$items = $list->children($ns['lStk']); // then the items in that list
$products = [];
foreach ($items as $item)
{
$elements = $item->children($ns['stk'])->children($ns['stk']);
// ^^^ one less here compared to yours
$product = array_intersect_key((array)$elements, ['EAN' => 0, 'name' => 1]);
foreach ($elements->categories as $category) foreach ($category as $cat)
$product['category'][] = (string)$cat
;
$products[] = $product;
}
var_dump($products);
Output:
array(2) {
[0] => array(3) {
'EAN' => string(13) "8594011770127"
'name' => string(5) "Item1"
'category' => array(2) {
[0] => string(1) "5"
[1] => string(1) "6"
}
}
[1] => array(3) {
'EAN' => string(13) "8595557507840"
'name' => string(5) "Item2"
'category' => array(3) {
[0] => string(1) "6"
[1] => string(1) "9"
[2] => string(1) "1"
}
}
}
The code is a little different to yours but that is merely cosmetic. However it gives you some ideas how to not $count
and $i++
too much by just using an array.
For more ease of use with XML-Namespace and simplexml especially with traversal, normally xpath helps here dramatically:
$xml = simplexml_load_file($path_to_xml_file);
$products = [];
$items = $xml->xpath('//lStk:listStock//stk:stockHeader');
foreach ($items as $item)
{
$product = array_intersect_key((array)$item->children('stk', TRUE), ['EAN' => 0, 'name' => 1]);
$product['category'] = array_map('intval', $item->xpath('*[local-name()="categories"]/*'));
$products[] = $product;
}