I have an xml where i have to parse the categories and store them in db.The categories have child categories and child categories have sub child categories.It is like tree structure.I need a recursive function to fetch the sub categories if a category have subcategory.I need to store categoryid,categoryname,parentcategoryid in db.
This is my xml
<test>
<categorylist>
<categoryitem>
<id>
<![CDATA[ 47 ]]>
</id>
<name>
<![CDATA[ Homeparties ]]>
</name>
</categoryitem>
<categoryitem>
<id>
<![CDATA[ 86 ]]>
</id>
<name>
<![CDATA[ All Products ]]>
</name>
</categoryitem>
<categoryitem>
<id>
<![CDATA[ 111 ]]>
</id>
<name>
<![CDATA[ Machines ]]>
</name>
<categorylist>
<categoryitem>
<id>
<![CDATA[ 1147 ]]>
</id>
<name>
<![CDATA[ Machine Colours ]]>
</name>
<categorylist>
<categoryitem>
<id>
<![CDATA[ 1397 ]]>
</id>
<name>
<![CDATA[ Black ]]>
</name>
</categoryitem>
</categorylist>
</categoryitem>
</categorylist>
</categoryitem>
</categorylist>
</test>
store them as category_id category_name parent_category_id
for the above i have tried like this.It is working fine for some levels like upto three levels.suppose if it is n levels,I need a recursive fuction.The below is my code.
if($xml){
$this->fetchCategoriesRecursive($xml);
}
public function fetchCategoriesRecursive($categories)
{
foreach($categories->{'categorylist'}->{'categoryitem'} as $category)
{
$this->insertCategory($category);
foreach($category->{'categorylist'}->{'categoryitem'} as $category_child)
{
$this->insertCategory($category_child,$category->{'id'});
foreach($category_child->{'categorylist'}->{'categoryitem'} as $category_sub_child)
{
$this->insertCategory($category_sub_child,$category_child->{'id'});
}
}
}
}
public function insertCategory($category,$category_id)
{
$category_info=array();
$category_info = $this->_db->fetchCol("SELECT category_id FROM category_mapping");
$data = array();
$data['category_id'] = $category->{'id'};
$data['category_name'] = $category->{'name'};
$data['parent_category_id'] = $category_id;
if(!in_array($data['category_id'],$category_info))
{
$this->_db->insert('category_mapping', $data);
}
}
Here is no need for a recursion, you can iterate over all categoryitem
elements using Xpath. Each node knows its position inside the DOM. So you can fetch all categoryitem
parent elements and use the nearest (the first) one.
$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXpath($dom);
// iterate all categoryitem elements
foreach ($xpath->evaluate('//categoryitem') as $node) {
var_dump(
[
// fetch the id of the nearest categoryitem element on the ancestor axis
'parent_id' => $xpath->evaluate('string(ancestor::categoryitem[1]/id)', $node),
// fetch the id as string
'id' => $xpath->evaluate('string(id)', $node),
// fetch the name as string
'name' => $xpath->evaluate('string(name)', $node),
]
);
}
Output:
array(3) {
["parent_id"]=>
string(0) ""
["id"]=>
string(4) " 47 "
["name"]=>
string(13) " Homeparties "
}
array(3) {
["parent_id"]=>
string(0) ""
["id"]=>
string(4) " 86 "
["name"]=>
string(14) " All Products "
}
array(3) {
["parent_id"]=>
string(0) ""
["id"]=>
string(5) " 111 "
["name"]=>
string(10) " Machines "
}
array(3) {
["parent_id"]=>
string(5) " 111 "
["id"]=>
string(6) " 1147 "
["name"]=>
string(17) " Machine Colours "
}
array(3) {
["parent_id"]=>
string(6) " 1147 "
["id"]=>
string(6) " 1397 "
["name"]=>
string(7) " Black "
}