简体   繁体   中英

how to correctly append xml child elements in php

I'm trying to iterate over an array of movie names and am struggling as shown below. I've included the actual output vs expected output. thanks!

$root = new SimpleXMLElement('<movies/>');
$movies = ['foo', 'bar'];
foreach($movies as $movie_name){
    $movie_el = buildMovieTag($movie_name);
    $root->addChild($movie_el->asXML());
}


function buildMovieTag($name){
    $movie_tag = new SimpleXMLElement('<movie/>');
    $movie_tag->addChild('name', $name);
    return $movie_tag;
}

I'm expecting this:

<?xml version="1.0"?>
<movies>
<movie><name>foo</name></movie>
<movie><name>bar</name></movie>
</movies>

but am getting this:

<?xml version="1.0"?>
<movies><<?xml version="1.0"?>  // extra xml tag
<movie><name>foo</name></movie>
/><<?xml version="1.0"?> // extra xml tag
<movie><name>bar</name></movie>
/></movies>

The new SimpleXMLElement then asXML() is the issue.

addChild is enough to make the element then its return value is the node, then subsequent addChild's on the node make the children.

<?php
$root = new SimpleXMLElement('<movies/>');
$movies = ['foo', 'bar'];
foreach($movies as $movie_name) {
    $movie = $root->addChild('movie');
    buildMovieTag($movie, $movie_name);
}

function buildMovieTag($node, $name) {
    $node->addChild('name', $name);
}

echo $root->saveXML();
<?xml version="1.0"?>
<movies><movie><name>foo</name></movie><movie><name>bar</name></movie></movies>

Edit: if your data is more extensive, structure it so its standard key/value array then loop over the items. The actual issue to the original question is noted on the first line of the answer.

<?php
$root = new SimpleXMLElement('<movies/>');
$movies = [
    ['name'=>'foo', 'released' => '2020-12-01 00:00:00', 'plot' => 'foo is a foofoo'],
    ['name'=>'bar', 'released' => '2020-12-02 00:00:00', 'plot' => 'bar is a barbar'],
];
foreach ($movies as $movie) {
    buildMovieTag($root->addChild('movie'), $movie);
}

function buildMovieTag($node, $data) {
    foreach ($data as $key => $item) {
        // just year from datetime string
        if ($key === 'released') $item = date_create($item)->format('Y');
    
        $node->addChild($key, $item);
    }
}

echo $root->saveXML();

Result (manual formatted)

<?xml version="1.0"?>
<movies>
    <movie>
        <name>foo</name>
        <released>2020</released>
        <plot>foo is a foofoo</plot>
    </movie>
    <movie>
        <name>bar</name>
        <released>2020</released>
        <plot>bar is a barbar</plot>
    </movie>
</movies>

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM