Reputation: 265
I want get the whole XML contents, but the results only show node value, node attributes are missing.
XML File:
<main>
<people num="1">
<name num1="1">Jack</name>
<age num2="1">50</age>
</people>
</main>
The code is
$xml = simplexml_load_file("c:/www/Mongo/test2.xml");
$xml1=$xml->people;
var_dump($xml1);
Result:
object(SimpleXMLElement)#2 (3) { ["@attributes"]=> array(1) { ["num"]=>string(1) "1" } ["name"]=> string(4) "Jack" ["age"]=> string(2) "50" }
Name&Age node attributes are missing. I know the attributes could get by $xml->people->name, but how to get it only use $xml->people
Upvotes: 0
Views: 475
Reputation: 3701
The problem is that leaf nodes (e.g. name) can have both attributes (num1 = "1"
) and a value ("Jack"
). Just how should that be represented when converted into an array?
If we set $array['people']['name'] = "Jack"
, where would we store the attributes? We cannot use $array['people']['name']['@attributes'] = ['num1' => 1]
as that would overwrite the "Jack" value.
The code below presents one solution, where each (leaf) value is wrapped in a 'value'
element, e.g. $array['people']['name']['value'] = "Jack"
and the attributes have the standard '@attributes'
key, e.g. $array['people']['name']['@attributes'] = ['num1' => 1]
. This would work for simple XML like the one in your question but may not be suitable for more complicated documents.
Reading the comments I understand that you actually want to convert the XML into JSON, so that is what the following code does in the end:
// Some example XML (some elements added)
$src = <<<EOS
<main>
<people num="1">
<name num1="1">Jack</name>
<age num2="1">50</age>
<skills what="ever">
<skill type="minor">Cookie munching</skill>
<skill type="major">Cake gobbling</skill>
<skill>Candy gulping</skill>
</skills>
</people>
</main>
EOS;
// Create a DOM element from XML
$dom = new DOMDocument();
$dom->loadXML($src);
// Use a XPath query to get all leaf nodes (elements without
// element child nodes)
$xpath = new DOMXPath($dom);
foreach ($xpath->query('//*[not(*)]') as $leaf) {
// Create a new <value> element for each leaf node, moving
// the leaf value (first child) into that node.
// E.g. <name num1="1">Jack</name>
// => <name num1="1"><value>Jack</value></name>
$value = $dom->createElement('value');
$value->appendChild($leaf->firstChild);
$leaf->insertBefore($value);
}
// Turn into SimpleXMLElement and covert to JSON
$xml = simplexml_import_dom($dom);
$json = json_encode($xml, JSON_PRETTY_PRINT);
echo $json, PHP_EOL;
Output:
{
"people": {
"@attributes": {
"num": "1"
},
"name": {
"@attributes": {
"num1": "1"
},
"value": "Jack"
},
"age": {
"@attributes": {
"num2": "1"
},
"value": "50"
},
"skills": {
"@attributes": {
"what": "ever"
},
"skill": [
{
"@attributes": {
"type": "minor"
},
"value": "Cookie munching"
},
{
"@attributes": {
"type": "major"
},
"value": "Cake gobbling"
},
{
"value": "Candy gulping"
}
]
}
}
}
Upvotes: 3
Reputation: 173
Here is a better solution using json_encode, json_decode
echo '<pre>';
$xml = simplexml_load_file("n.xml");
$xml=json_decode(json_encode($xml),TRUE);
$xml1=$xml['people'];
print_r($xml1);
echo '<br>';
print_r($xml['people']['@attributes']['num']);
Output:
Array
(
[@attributes] => Array
(
[num] => 1
)
[name] => Jack
[age] => 50
)
1
So one last suggestion , probably you can change your XML data something like this
<?xml version="1.0" encoding="UTF-8"?>
<main>
<people num="1">
<name num1="1"><first_name>Jack</first_name></name>
<age num2="1"><years>50</years></age>
</people>
</main>
Output:
Array
(
[people] => Array
(
[@attributes] => Array
(
[num] => 1
)
[name] => Array
(
[@attributes] => Array
(
[num1] => 1
)
[first_name] => Jack
)
[age] => Array
(
[@attributes] => Array
(
[num2] => 1
)
[years] => 50
)
)
)
this should work for you. :)
Upvotes: 0