I have a XML in form of String (after XLS transform):
<course>
<topic>
<chapter>Some value</chapter>
<title>Some value</title>
<content>Some value</content>
</topic>
<topic>
<chapter>Some value</chapter>
<title>Some value</title>
<content>Some value</content>
</topic>
....
</course>
Then I'm pushing above mentioned XML into the Array():
$new_xml = $proc->transformToXML($xml);
$xml2 = simplexml_load_string($new_xml);
$root = $xml2->xpath("//topic");
$current = 0;
$topics_list = array();
// put the xml values into multidimensional array
foreach($root as $data) {
if ($data === 'chapter') {
$topics_list[$current]['chapter'] = $data->chapter;
}
if ($data === 'title') {
$topics_list[$current]['title'] = $data->title;
}
if ($data === 'content') {
$topics_list[$current]['content'] = $data->content;
}
$current++;
}
print_r($topics_list);
Problem: Result is empty array. I've tried string like:
$topics_list[$current]['chapter'] = (string) $data->chapter;
but result is still empty. Can anyone explain, where is my mistake. Thanks.
Because my topic element has only simple child elements and not attributes, I can cast it to array and add it to the list (Demo):
$xml2 = SimpleXMLElement($new_xml);
$topics_list = array();
foreach ($xml2->children() as $data) {
$topics_list[] = (array) $data;
}
The alternative method is to map get_object_vars
on the topic elements (Demo):
$topics_list = array_map('get_object_vars', iterator_to_array($xml2->topic, false));
But that might become a bit hard to read/follow. Foreach is probably more appropriate.
And here is the first working version of my code:
$xml2 = SimpleXMLElement($new_xml);
$current = 0;
$topics_list = array();
foreach($xml2->children() as $data) {
$topics_list[$current]['chapter'] = (string) $data->chapter;
$topics_list[$current]['title'] = (string) $data->title;
$topics_list[$current]['content'] = (string) $data->content;
$current++;
}
Thanks again to @Jack, @CoursesWeb and @fab for their investigation.
The problem is that you not get the name of the xml element.
To get the name of the xml element, apply elm->getName()
In your code should be:
if ($data->getName() === 'chapter')
For more details about traversing and getting xml elements with Simplexml, see this tutorial: http://coursesweb.net/php-mysql/php-simplexml
There are several mistakes.
1. return value of xpath()
$root = $xml2->xpath("//topic");
Here you assign $root
to a list of all nodes retrieved by the XPath //topic
. So, when you iterate over it with
foreach($root as $data)
$data refers to each of the <topic>
elements, not the children of those.
2. comparison of SimpleXMLElements with strings
Let's assume, you loop over the right elements and $data
refers to the <chapter>
element: then the following expressions are true:
$data == 'Some value'
(string) $data === 'Some value'
But you cannot do a type safe comparison (===
) between a SimpleXMLElement and a string, and the conversion to string does not result in the element name. What you want to do is:
if ($data->getName() === 'chapter')
3. how to get the text value
it should already be clear from the explanation above but you also will have to replace
$data->chapter
with
(string) $data