262

I have to generate a xml file dynamically at runtime. Please help me in generating the below XML file dynamically using PHP.

<?xml version="1.0" encoding="UTF-8"?>
<xml>
 <track>
     <path>song1.mp3</path>
     <title>Track 1 - Track Title</title>
 </track>
 <track>
     <path>song2.mp3</path>
     <title>Track 2 - Track Title</title>
 </track>
 <track>
     <path>song3.mp3</path>
     <title>Track 3 - Track Title</title>
 </track>
 <track>
     <path>song4.mp3</path>
     <title>Track 4 - Track Title</title>
 </track>
 <track>
     <path>song5.mp3</path>
     <title>Track 5 - Track Title</title>
 </track>
 <track>
     <path>song6.mp3</path>
     <title>Track 6 - Track Title</title>
 </track>
 <track>
     <path>song7.mp3</path>
     <title>Track 7 - Track Title</title>
 </track>
 <track>
     <path>song8.mp3</path>
     <title>Track 8 - Track Title</title>
 </track>

hakre
  • 193,403
  • 52
  • 435
  • 836
musicking123
  • 3,385
  • 9
  • 32
  • 33

8 Answers8

382

I'd use SimpleXMLElement.

<?php

$xml = new SimpleXMLElement('<xml/>');

for ($i = 1; $i <= 8; ++$i) {
    $track = $xml->addChild('track');
    $track->addChild('path', "song$i.mp3");
    $track->addChild('title', "Track $i - Track Title");
}

Header('Content-type: text/xml');
print($xml->asXML());

?>

$xml->asXML() can also take a filename as a parameter to save to that file

Matthew Lock
  • 13,144
  • 12
  • 92
  • 130
Ivan Krechetov
  • 18,802
  • 8
  • 49
  • 60
  • 12
    It is possible to specify the encoding with SimpleXml? How it can be done? – Eineki Jan 28 '09 at 14:17
  • 1
    Hi,I tried ur example but in the validation i am getting 2 warnings.how to clear them? http://validator.w3.org/check?uri=http%3A%2F%2F61.8.156.158%2FListMyCompany%2Ffeed.php&charset=%28detect+automatically%29&doctype=Inline&ss=1&outline=1&group=0&No200=1&verbose=1&user-agent=W3C_Validator%2F1.1 – Satya Jan 13 '11 at 07:52
  • 3
    @Eineki just add the `` processing instruction. I believe, SimpleXMLElement will do the right thing: converting all the queried string values to your mb_internal_encoding. – Ivan Krechetov Jan 29 '13 at 09:07
  • 33
    `$xml = new SimpleXMLElement(""); ` – Kevin Florenz Daus Apr 16 '13 at 06:54
  • I get 'error on line 2 at column 6: XML declaration allowed only at the start of the document' ; the code adds extra empty line at the beginning of the xml which causes parsing error. – Elia Weiss Dec 06 '15 at 14:24
  • Example generates one long line instead breaking by XML elements – JackTheKnife Jan 19 '16 at 21:23
  • **Warning!** `addChild` doesn't fully escape the child value which may cause an invalid XML. You need to escape the `&` character or use a magic property. More details here: http://php.net/manual/en/simplexmlelement.addchild.php#112204 – Finesse Oct 09 '17 at 12:10
  • if some one want to read a tutorial then here is one to generate xml using php http://programmerblog.net/how-to-generate-xml-files-using-php – Maz I Nov 22 '17 at 07:13
  • 1
    This for some reason did not work for me, would not create xml file. The answer below worked. – TheTechGuy Mar 16 '19 at 12:12
191

To create an XMLdocument in PHP you should instance a DOMDocument class, create child nodes and append these nodes in the correct branch of the document tree.

For reference you can read https://www.php.net/manual/en/book.dom.php

Now we will take a quick tour of the code below.

  • at line 2 we create an empty xml document (just specify xml version (1.0) and encoding (utf8))
  • now we need to populate the xml tree:
    • We have to create an xmlnode (line 5)
    • and we have to append this in the correct position. We are creating the root so we append this directly to the domdocument.
    • Note create element append the element to the node and return the node inserted, we save this reference to append the track nodes to the root node (incidentally called xml).

These are the basics, you can create and append a node in just a line (13th, for example), you can do a lot of other things with the dom api. It is up to you.

<?php    
    /* create a dom document with encoding utf8 */
    $domtree = new DOMDocument('1.0', 'UTF-8');

    /* create the root element of the xml tree */
    $xmlRoot = $domtree->createElement("xml");
    /* append it to the document created */
    $xmlRoot = $domtree->appendChild($xmlRoot);



    /* you should enclose the following lines in a loop */
    $currentTrack = $domtree->createElement("track");
    $currentTrack = $xmlRoot->appendChild($currentTrack);
    $currentTrack->appendChild($domtree->createElement('path','song1.mp3'));
    $currentTrack->appendChild($domtree->createElement('title','title of song1.mp3'));

    $currentTrack = $domtree->createElement("track");
    $currentTrack = $xmlRoot->appendChild($currentTrack);
    $currentTrack->appendChild($domtree->createElement('path','song2.mp3'));
    $currentTrack->appendChild($domtree->createElement('title','title of song2.mp3'));

    /* get the xml printed */
    echo $domtree->saveXML();
?>

Edit: Just one other hint: The main advantage of using an xmldocument (the dom document one or the simplexml one) instead of printing the xml,is that the xmltree is searchable with xpath query

Eineki
  • 14,773
  • 6
  • 50
  • 59
  • hi, thanks. how can i specify the path where his file resides? – guitarlass May 29 '12 at 08:33
  • 7
    can i again use `$domtree->save('mypath/xmlfile.xml');` ? – guitarlass May 29 '12 at 08:46
  • 1
    @guitarlass You are right. [save](http://it.php.net/manual/en/domdocument.save.php) and [saveXML](http://it.php.net/manual/en/domdocument.savexml.php) are similar: the first dump the xmltree into a file, the second into a string (and you can save it in a following step with normal file saving directives). – Eineki May 29 '12 at 13:13
  • @jjonesdesign uh... i thought that programmers should be lazy: http://threevirtues.com/ – Julian Aug 11 '15 at 11:41
  • 4
    @jjonesdesign You have to work hard to obtain the knowledge needed to be lazy :) – Eineki Aug 14 '15 at 07:11
  • 2
    Example generates one long line instead breaking by XML elements. You need to add `$domtree->formatOutput = true;` to make the output pretty :) – JackTheKnife Jan 19 '16 at 21:23
  • It is a good observation, @JackTheKnife. You know, formatting the output you are diverting from the [canonical form](https://en.wikipedia.org/wiki/Canonical_XML) of your xml document. I prefer have such a form and format the results only on purpose. In similar cases, I suspect it is just a matter of personal taste, though – Eineki Jan 22 '16 at 14:09
  • You can make it pretty by using `$domtree->formatOutput = true; ` after new – TheTechGuy Mar 16 '19 at 12:11
  • How can I download this xml file instead of saving in a specific path? – Drenyl Sep 12 '19 at 00:30
  • 1
    @Drenyl add an appropriate content-type header and a `Content-Disposition: attachment` and print the saveXml result. You can also suggest a filename. – Eineki Sep 12 '19 at 08:29
  • @Eineki I am following your code. Does it help me to create a group of elements within another? For example like this (thank you): https://prnt.sc/10dvadg – Neftali Acosta Mar 05 '21 at 19:16
  • @NeftaliAcosta Yes, it already do. Think of the $currentTrack / track element as your `direccion` element. and `estado`, `municipio` and `localidad` as the `path` and `title` elements in the example above – Eineki Mar 05 '21 at 21:48
28

An easily broken way to do this is :

<?php
// Send the headers
header('Content-type: text/xml');
header('Pragma: public');
header('Cache-control: private');
header('Expires: -1');
echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>";

echo '<xml>';

// echo some dynamically generated content here
/*
<track>
    <path>song_path</path>
    <title>track_number - track_title</title>
</track>
*/

echo '</xml>';

?>

save it as .php

miken32
  • 42,008
  • 16
  • 111
  • 154
andyk
  • 10,019
  • 10
  • 36
  • 41
  • 19
    easy, but prone to errors when variables are interpolated that have XML metacharacters in them such as angle brackets and ampersands – Matthew Lock Oct 12 '11 at 11:38
  • @MatthewLock This is true. This failed immediately no matter what I did (including document padding trim). This solution is hardly feasible. – WiiLF Nov 13 '22 at 01:00
16

With FluidXML you can generate your XML very easly.

$tracks = fluidxml('xml');

$tracks->times(8, function ($i) {
    $this->add([
        'track' => [
            'path'  => "song{$i}.mp3",
            'title' => "Track {$i} - Track Title"
        ]
    ]);

});

https://github.com/servo-php/fluidxml

Daniele Orlando
  • 2,692
  • 3
  • 23
  • 26
6

Hope this code may help you out. Easy and simple solution

$dom = new DOMDocument();
$dom->encoding = 'utf-8';
$dom->xmlVersion = '1.0';
$dom->formatOutput = true;
$xml_file_name = './movies_list.xml'; //You can give your path to save file.
$root = $dom->createElement('Movies');
    $movie_node = $dom->createElement('movie');
    $attr_movie_id = new DOMAttr('movie_id', '5467');
    $movie_node->setAttributeNode($attr_movie_id);
        
        $child_node_title = $dom->createElement('Title', 'The Campaign');
        $movie_node->appendChild($child_node_title);
        
        $child_node_year = $dom->createElement('Year', 2012);
        $movie_node->appendChild($child_node_year);
        
        $child_node_genre = $dom->createElement('Genre', 'The Campaign');
        $movie_node->appendChild($child_node_genre);
        
        $child_node_ratings = $dom->createElement('Ratings', 6.2);
        $movie_node->appendChild($child_node_ratings);
    $root->appendChild($movie_node);
$dom->appendChild($root);
$dom->save($xml_file_name);

For more information visit this to get information in details: https://www.guru99.com/php-and-xml.html

Atmiya Kolsawala
  • 475
  • 4
  • 12
4

Take a look at the Tiny But Strong templating system. It's generally used for templating HTML but there's an extension that works with XML files. I use this extensively for creating reports where I can have one code file and two template files - htm and xml - and the user can then choose whether to send a report to screen or spreadsheet.

Another advantage is you don't have to code the xml from scratch, in some cases I've been wanting to export very large complex spreadsheets, and instead of having to code all the export all that is required is to save an existing spreadsheet in xml and substitute in code tags where data output is required. It's a quick and a very efficient way to work.

Cruachan
  • 15,733
  • 5
  • 59
  • 112
4

I see examples with both DOM and SimpleXML, but none with the XMLWriter.

Please keep in mind that from the tests I've done, both DOM and SimpleXML are almost twice slower then the XMLWriter and for larger files you should consider using the later one.

Here's a full working example, clear and simple that meets the requirements, written with XMLWriter (I'm sure it will help other users):

// array with the key / value pairs of the information to be added (can be an array with the data fetched from db as well)
$songs = [
    'song1.mp3' => 'Track 1 - Track Title',
    'song2.mp3' => 'Track 2 - Track Title',
    'song3.mp3' => 'Track 3 - Track Title',
    'song4.mp3' => 'Track 4 - Track Title',
    'song5.mp3' => 'Track 5 - Track Title',
    'song6.mp3' => 'Track 6 - Track Title',
    'song7.mp3' => 'Track 7 - Track Title',
    'song8.mp3' => 'Track 8 - Track Title',
];

$xml = new XMLWriter();
$xml->openURI('songs.xml');
$xml->setIndent(true);
$xml->setIndentString('    ');
$xml->startDocument('1.0', 'UTF-8');
    $xml->startElement('xml');
            foreach($songs as $song => $track){
                $xml->startElement('track');
                    $xml->writeElement('path', $song);
                    $xml->writeElement('title', $track);
                $xml->endElement();
            }
    $xml->endElement();
$xml->endDocument();
$xml->flush();
unset($xml);
nersi1
  • 109
  • 4
-14
$query=mysql_query("select * from tablename")or die(mysql_error()); 
$xml="<libraray>\n\t\t";
while($data=mysql_fetch_array($query))
{

    $xml .="<mail_address>\n\t\t";
    $xml .= "<id>".$data['id']."</id>\n\t\t";
    $xml .= "<email>".$data['email_address']."</email>\n\t\t";
    $xml .= "<verify_code>".$data['verify']."</verify_code>\n\t\t";
    $xml .= "<status>".$data['status']."</status>\n\t\t";
    $xml.="</mail_address>\n\t";
}
$xml.="</libraray>\n\r";
$xmlobj=new SimpleXMLElement($xml);
$xmlobj->asXML("text.xml");

Its simple just connect with your database it will create test.xml file in your project folder

pratik
  • 983
  • 3
  • 13
  • 25
  • 27
    This is the kind of code that should never see production. Depending on the data you ouput, you might create invalid (i.e. unparseable) XML. It's sloppy at best, and even though it might seem easy because you may save a few lines of code, it will cost you more later in terms of maintenance and debugging; not to mention the poor guy who some day might take over the responsibility of your work. – Arne Aug 12 '14 at 08:39
  • 3
    -1 first concanating a string with some wanna-be-xml, then pushing that string into SimpleXML - This looks just flipped upside down. Instead *first* initialize the XML library object, *then* use it to build up the XML. It's easier, uses less memory, is less error prone and allows you to stream out the XML to file or stdout. – hakre Aug 23 '14 at 09:47
  • 3
    Maybe it's time to delete this answer (and you will get your lost reputation back!). – Jose Manuel Abarca Rodríguez Feb 08 '19 at 14:39
  • 2
    I think it should stay. I made some code myself first time working with XML and it looked a bit like this, so it was very helpful to see what NOT to do. – Peter Højlund Palluth Feb 29 '20 at 12:24