CSV to XML Conversion

I needed a tool to convert a pretty large file from CSV to XML for a project for work. I looked around for a ready-made one in C++ and couldn’t find it. I looked for a web one and couldn’t find one. So I did what any respectable programmer does. I made my own. I tried to scratch something together in C++, but that gave me all sorts of grief. It probably doesn’t help that I haven’t had to deal with simple file I/O since college. Frustrated, I turned to my friend PHP.

If you would like to see the final result, see the Demo page.

I used 4 PHP files to make this work:

  • csvtoxml.php – This is the main entry point where the user browses for a file to upload and enters some parameters.
  • upload_file.php – This is the code that uploads the selected file to a directory. lets the user select the output format, and heads to the next PHP file for processing.
  • xmloutput.php – This does what you’d expect – it generates the xml output based on the headers of the CSV and the parameters. It deletes the original file.
  • xmlDownload.php – If the user selected to download the XML file, this is the page that does the dirty work.

Here is the code for the files:

csvtoxml.php

<?php
 echo"<form action='upload_file.php' method='post'
 enctype='multipart/form-data'>
 <label for='file'>Filename:</label>
 <input type='file' name='file' id='file' />
 <br /><br />
 Name at Container Level: <input type='text' name='container' />
 <br /><br />
 Name at Row Level: <input type='text' name='rows' />
 <br /><br />
 Schema Filename: <input type='text' name='schema' />
 <br /><br />
 <input type='radio' name='testnozzle' value='nonozzle' /> Run this using normal parameters<br />
 <input type='radio' name='testnozzle' value='nozzle' /> Run this using Test Nozzle CSV Parameters
 <br /><br />
 <input type='submit' value='Submit'/>
 </form>";
 ?>

upload_file.php

<?php
 // A little preformatting to block unwanted filetypes
 $allowedExtensions = array("csv");
 foreach ($_FILES as $file) {
 if ($file['tmp_name'] > '') {
 if (!in_array(end(explode(".",
 strtolower($file['name']))),
 $allowedExtensions)) {
 die($file['name'].' is an invalid file type!<br/>'.
 '<a href="javascript:history.go(-1);">'.
 '&lt;&lt Go Back</a>');
 }
 }
 }

 $fileloc = $_FILES['uploadedfile']['name'];
 echo "Your file is located at " . $fileloc . "\n";
 if ($_FILES["file"]["error"] > 0)
 {
 echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
 }
 else
 {
 echo "Upload: " . $_FILES["file"]["name"] . "<br />";
 echo "Type: " . $_FILES["file"]["type"] . "<br />";
 echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
 echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";

 if (file_exists("upload/" . $_FILES["file"]["name"]))
 {
 echo $_FILES["file"]["name"] . " already exists. ";
 }
 else
 {
 move_uploaded_file($_FILES["file"]["tmp_name"],
 "upload/" . $_FILES["file"]["name"]);
 echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
 }
 }

 $filename = "upload/" . $_FILES["file"]["name"];
 $level1 = $_REQUEST['container'];
 $level2 = $_REQUEST['rows'];
 $schema = $_REQUEST['schema'];
 $nozzle = $_REQUEST['testnozzle'];

 echo "<form action='xmloutput.php' method='post'>
 <input type='hidden' name='filename' value=$filename>
 <input type='hidden' name='containtitle' value=$level1>
 <input type='hidden' name='rowtitle' value=$level2>
 <input type='hidden' name='schemastr' value=$schema>
 <input type='hidden' name='nozzle' value=$nozzle>
 <br />
 <input type='radio' name='output' value='display' /> Display the XML<br />
 <input type='radio' name='output' value='file' /> Save the XML to File
 <br /><br />
 <input type='submit' value='Submit'/>
 <br /> <em>This may take some time for large files</em>";
?>

xmloutput.php

<?php
function csv2xml($file, $container = 'data', $rows = 'row',$schema,$testnozzle)
{
 $r = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
 $r .= "Export xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"{$schema}\"\n";
 $r .= "<{$container}>\n";
 $row = 0;
 $cols = 0;
 $titles = array();
 $firstrun = true;

 $handle = @fopen($file, 'r');
 if (!$handle) return $handle;

 while (($data = fgetcsv($handle, 1000, ',')) !== FALSE)
 {

 if (!$cols) $cols = count($data);
 // if this is a nozzle test csv for work
 if($testnozzle == 'nozzle')
 {
 $index = $data[0];
 $color = $data[1];
 $noznum = $data[2];
 // if the noznum is 0, we're starting a new printhead, so output new tag
 if($noznum == '0')
 {
 if($firstrun == false)
 {
 $r .= "\t</Color>\n";
 }
 else
 {
 $r .= "\t<Barcode>L0123456789</Barcode>\n";
 }
 $r .= "\t<Color ID=\"{$color}\" NumCols=\"41\" ColTypes=\"ISIFFFFFFFFFFFFFFFFFFIFFFFFFFFFFFIFIFFFIFFI\">\n";
 $firstrun = false;
 }
 // for every row of data, put the nozzle number in the tag
 if ($row > 0) $r .= "\t\t<{$rows} ID=\"{$noznum}\">\n";
 for ($i = 0; $i < $cols; $i++)
 {
 if ($row == 0)
 {
 $titles[$i] = $data[$i];
 continue;
 }

 $r .= "\t\t\t<{$titles[$i]}>";
 $r .= $data[$i];
 $r .= "</{$titles[$i]}>\n";
 }
 if ($row > 0) $r .= "\t\t</{$rows}>\n";
 $row++;
 }
 else
 {
 if ($row > 0) $r .= "\t\t<{$rows}>\n";

 for ($i = 0; $i < $cols; $i++)
 {
 if ($row == 0)
 {
 $titles[$i] = $data[$i];
 continue;
 }

 $r .= "\t\t<{$titles[$i]}>";
 $r .= $data[$i];
 $r .= "</{$titles[$i]}>\n";
 }
 if ($row > 0) $r .= "\t</{$rows}>\n";
 $row++;
 }
 }
 fclose($handle);
 if (!unlink($file))
 {
 echo ("Error deleting $file");
 }
 if($testnozzle == 'nozzle')
 {
 $r .= "\t</Color>\n";
 }
 $r .= "</{$container}>";

 return $r;
}

 header("Content-type: text/xml");

 $filename = $_REQUEST['filename'];
 $level1 = $_REQUEST['containtitle'];
 $level2 = $_REQUEST['rowtitle'];
 $schema = $_REQUEST['schemastr'];
 $testnozzle = $_REQUEST['nozzle'];
 $output = $_REQUEST['output'];                        

 $xml = csv2xml($filename,$level1,$level2,$schema,$testnozzle);

 //$File = $filename;
 $File .= "newFromCSV.xml";
 $Handle = fopen($File, 'w');
 fwrite($Handle, $xml);
 fclose($Handle);

 if($output == "file")
 {
 header('Location: xmlDownload.php');
 }
 else
 {
 echo($xml);
 }    

?>

xmlDownload.php

<?php
// We'll be outputting XML
header('Content-type: application/xml');

// It will be called downloaded.xml
header('Content-Disposition: attachment; filename="download.xml"');

// The XML source is in original.xml
readfile('./newFromCSV.xml');
?>

If I get some downtime (HA!) I’ll try to go in and add some comments later.

Author: Steph

Share This Post On

Pin It on Pinterest

Share This