I have an xml document below:
<?xml version="1.0" encoding="UTF-8" ?>
<books>
<book>
<name>Title One</name>
<year>2014</year>
<authors>
<author>
<name>Author One</name>
</author>
</authors>
</book>
<book serie="yes">
<name>Title Two</name>
<year>2015</year>
<authors>
<author>
<name>Author two</name>
</author>
<author>
<name>Author three</name>
</author>
</authors>
</book>
<book serie="no">
<name>Title Three</name>
<year>2015</year>
<authors>
<author>
<name>Author four</name>
</author>
</authors>
</book>
</books>
I want to convert it into an array bellow.
array(
array('Tittle one', 2014, 'Author One'),
array('Tittle two', 2015, 'Author two, Author three'),
array('Tittle three', 2015, 'Author four'),
);
My code below is failing to produce the array structure that I would want:
function arrayRepresentation(){
$xmldoc = new DOMDocument();
$xmldoc->load("data/data.xml");
$parentArray = array();
foreach ($xmldoc->getElementsByTagName('book') as $item) {
$parentArray[] = array_generate($item);
}
var_dump($parentArray);
}
function array_generate($item){
$movieArray = array();
$childMovieArray = array();
for ($i = 0; $i < $item->childNodes->length; ++$i) {
$child = $item->childNodes->item($i);
if ($child->nodeType == XML_ELEMENT_NODE) {
if(hasChild($child)){
$childMovieArray = array_generate($child);
}
}
$movieArray[] = trim($child->nodeValue);
}
if(!empty($childMovieArray)){
$movieArray = array_merge($movieArray,$childMovieArray);
}
return $movieArray;
}
function hasChild($p)
{
if ($p->hasChildNodes()) {
foreach ($p->childNodes as $c) {
if ($c->nodeType == XML_ELEMENT_NODE)
return true;
}
}
}
arrayRepresentation();
Basically I am looping through the the nodes to get xml element values. I am then checking if I Node has more child nodes and if it has I loop through it again to get the values. I am failling to deduce a way that: (i) will not give me some empty array elements (ii) Check for any child nodes and put all the xml sibling elements in a single string
PHPs DOM supports Xpath expressions for fetching specific nodes and values. That drastically reduces the amount of loops and conditions you will need.
Here is a demo:
// bootstrap the XML document
$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);
$data = [];
// iterate the node element nodes
foreach ($xpath->evaluate('/books/book') as $book) {
$authors = array_map(
fn ($node) => $node->textContent,
// fetch author name nodes as an array
iterator_to_array($xpath->evaluate('authors/author/name', $book))
);
$data[] = [
// cast first name element child to string
$xpath->evaluate('string(name)', $book),
// cast first year element child to string
$xpath->evaluate('string(year)', $book),
implode(', ', $authors)
];
}
var_dump($data);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.