Reputation: 2736
I have following XML:
<?xml version="1.0" encoding="Windows-1250"?>
<rsp:responsePack version="2.0" id="Za001" state="ok" note="" programVersion="10600.125 E1 (22.1.2014)"
xmlns:rsp="http://www.stormware.cz/schema/version_2/response.xsd"
xmlns:lst="http://www.stormware.cz/schema/version_2/list.xsd"
xmlns:lStk="http://www.stormware.cz/schema/version_2/list_stock.xsd"
xmlns:stk="http://www.stormware.cz/schema/version_2/stock.xsd">
<rsp:responsePackItem version="2.0" id="a55" state="ok">
<lStk:listStock version="2.0" dateTimeStamp="2014-04-18T22:36:44" dateValidFrom="2014-04-18" state="ok">
<lStk:stock version="2.0">
<stk:stockHeader>
<stk:id>101</stk:id>
<stk:EAN>8594011770127</stk:EAN>
<stk:isSales>true</stk:isSales>
<stk:name>Item1</stk:name>
<stk:categories>
<stk:idCategory>5</stk:idCategory>
<stk:idCategory>6</stk:idCategory>
</stk:categories>
</stk:stockHeader>
</lStk:stock>
<lStk:stock version="2.0">
<stk:stockHeader>
<stk:id>114</stk:id>
<stk:EAN>8595557507840</stk:EAN>
<stk:name>Item2</stk:name>
<stk:categories>
<stk:idCategory>6</stk:idCategory>
<stk:idCategory>9</stk:idCategory>
<stk:idCategory>1</stk:idCategory>
</stk:categories>
</stk:stockHeader>
</lStk:stock>
</lStk:listStock>
</rsp:responsePackItem>
</rsp:responsePack>
There are two items with the lStk:stock
attribute, and foreach of them I would need to get some values.
My current code is:
$xml=simplexml_load_file("import.xml");
if ($xml) {
$ns = $xml->getDocNamespaces();
$data = $xml->children($ns['rsp']);
$items = $data->children($ns['lStk']);
foreach ($items as $item) {
$counter = 0;
$elements = $item->children($ns['lStk'])->children($ns['stk'])->children($ns['stk']);
$products[$counter]['ean'] = $elements->EAN;
$products[$counter]['name'] = $elements->name;
$products[$counter]['count'] = $elements->count;
$i = 0;
foreach ($elements->categories as $category) {
/** @var $ class_name */
foreach ($category as $cat) {
/** @var $cat class_name */
$products[$counter]['category'][$i] = $cat;
$i++;
}
}
}
}
var_dump($products);
Which returns the info only for the first product. How should I change it to get both products?
Upvotes: 0
Views: 351
Reputation: 197684
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;
}
Upvotes: 1