Reputation: 57
I'm trying to transform XML into Json via PHP and I don't know how to serialize objects. Basically, I have in input an XML file (file.xml) with a recursive structure and I would like to transpose it into Json (out.json).
xml file sample:
<Transfer>
<Name>Transfer</Name>
<Title>Transfer + Date</Title>
<Level1>
<Name>Item 1</Name>
<Title>Title 1</Title>
<className>middle-level</className>
<Level2>
<Name>Item 1.1</Name>
<Title>Title 1.1</Title>
<className>product-dept</className>
</Level2>
<Level2>
<Name>Item 1.2</Name>
<Title>Title 1.2</Title>
<className>product-dept</className>
<Level3>
<Name>Item 1.2.1</Name>
<Title>Title 1.2.1</Title>
<className>pipeline1</className>
</Level3>
<Level3>
<Name>Item 1.2.2</Name>
<Title>Title 1.2.2</Title>
<className>pipeline1</className>
</Level3>
</Level2>
</Level1>
<Level1>
<Name>Item 2</Name>
<Title>Title 2</Title>
<className>middle-level</className>
</Level1>
</Transfer>
Json output desired :
{
'name': 'Transfer',
'title': 'transfer Date',
'children': [
{ 'name': 'Item 1', 'title': 'Title 1', 'className': 'middle-level',
'children': [
{ 'name': 'Item 1.1', 'title': 'Title 1.1', 'className': 'product-dept' },
{ 'name': 'Item 1.2', 'title': 'Title 1.2', 'className': 'product-dept',
'children': [
{ 'name': 'Item 1.2.1', 'title': 'Title 1.2.1', 'className': 'pipeline1' },
{ 'name': 'Item 1.2.2', 'title': 'Title 1.2.2', 'className': 'pipeline1' },
]
}
]
},
{ 'name': 'Item 2', 'title': 'Title 2', 'className': 'middle-level'}
]
}
All this with php code :
$xml = simplexml_load_file("file.xml");
$result = [];
foreach ($xml->Level1 as $value)
{
$child = [];
$child['Name'] = (string)$value->Name;
$child['Title'] = (string)$value->Title;
$child['className'] = (string)$value->className;
foreach ($xml->Level2 as $level2)
{
$child = [];
$child['Level2'] = (string)$value->Level2->Name;
}
$result[] = $child;
}
$json_string = json_encode($result);
print_r($json_string);
Currently, I'm just transforming a part of the graph but I don't understand how to do more. I think that what I want to do is not too complex but I am blocked.
Thanks for the help.
Upvotes: 2
Views: 80
Reputation: 659
When working with a structure of unkown depth, the stack is usually your best friend:
function xmlToJson($node, $level = 1)
{
$children = [];
if (isset($node->${'Level' . $level})) {
foreach ($node->${'Level' . $level} as $value) {
$children[] = [
'name' => (string)$value->Name,
'title' => (string)$value->Title,
'className' => (string)$value->className,
'children' => xmlToJson($value, $level + 1),
];
}
}
return $children;
}
This code will start at level one and fetch all the names, titles and classNames. Then it calls itself, creating a recursive function. Because of this, you need to make sure that level exists, hence the if (isset(...))
before actually accessing the level.
The function will terminate if it stops calling itself, which is when there are no more levels to descent down to.
Upvotes: 1
Reputation: 26
Try this
$xml = simplexml_load_string($xml);
$result = [];
$result['name'] = (string)$xml->Name;
$result['title'] = (string)$xml->Title;
foreach ($xml->Level1 as $value)
{
$child = [];
$item = [];
$item['name'] = (string)$value->Name;
$item['title'] = (string)$value->Title;
$item['className'] = (string)$value->className;
foreach ($value->Level2 as $level2)
{
$child2 = [];
foreach ($level2->Level3 as $level3) {
$child2[] = array(
'name' => (string)$level3->Name,
'title' => (string)$level3->Title,
'className' => (string)$level3->className,
);
}
$child[] = array(
'name' => (string)$level2->Name,
'title' => (string)$level2->Title,
'className' => (string)$level2->className,
'children' => $child2,
);
}
$item['children'] = $child;
$result['children'][] = $item;
}
$json_string = json_encode($result);
print_r($json_string);
Upvotes: 0