I have made this php script to convert CSV files into XML files. I have a for each loop that handles the records and the contents within this section. Which produces the following results.
I have been adding the same loop to contain details within the root station to contain the results as pictured
But when I add this same loop to read the root it seems to break, as seems to crash. Even while trail and error, starting with just this section within the code and removing the but to no avail.
Also within in this some entries (data-481.xml) are empty but within the google drive have lines within the information for the data-481.csv.
Blank XML - data-481.csv https://drive.google.com/file/d/1pEinOeosPQQRoeQoJHfEb6L_80iD5bqr/view?usp=share_link
<?php
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);
// List of CSV files
$csvFiles = [
'data-203.csv',
'data-206.csv',
'.....'
];
// Loop through each CSV file
foreach ($csvFiles as $csvFile) {
$csvFilePath = __DIR__ . '/' . $csvFile;
// Open the CSV file
if (($handle = fopen($csvFilePath, 'r')) !== false) {
// Create an XMLWriter instance
$xmlWriter = new XMLWriter();
$xmlWriter->openURI(csvFileToXmlFile($csvFile));
$xmlWriter->startDocument('1.0', 'UTF-8');
$xmlWriter->startElement('Station');
// Read the CSV file line by line
while (($data = fgetcsv($handle,10000,';')) !== false) {
// Skip empty lines
if (count($data) === 0) {
continue;
}
// Ensure the array has the necessary indexes
if (count($data) >= 4) {
// Extract the necessary data
$timestamp = $data[0];
$nox = $data[1];
$no2 = $data[2];
$no = $data[3];
// Check if the attribute has a value
if (trim($no) !== '') {
// Start XML record element
$xmlWriter->startElement('rec');
$xmlWriter->writeAttribute('ts', $timestamp);
$xmlWriter->writeAttribute('nox', $nox);
$xmlWriter->writeAttribute('no2', $no2);
$xmlWriter->writeAttribute('no', $no);
// End XML record element
$xmlWriter->endElement();
}
}
}
// Close XML elements and file
$xmlWriter->endElement();
$xmlWriter->endDocument();
$xmlWriter->flush();
fclose($handle);
// Output success message
$xmlFile = csvFileToXmlFile($csvFile);
echo "XML file generated successfully: $xmlFile\n";
}
}
// Function to convert CSV file name to XML file name
function csvFileToXmlFile($csvFile) {
$fileParts = pathinfo($csvFile);
$xmlFile = $fileParts['filename'] . '.xml';
return $xmlFile;
}
?>
I am hoping to have all the files transfer into XML from the CSV with the desired <station element to hold <station id="481 location="Bath Road" geocode="51.3453, -2.55434">
Some changes made, first to ensure a valid XML file, and secondly to pull the right data from the right place
// Loop through each CSV file
foreach ($csvFiles as $csvFile) {
$csvFilePath = __DIR__ . '/' . $csvFile;
// Open the CSV file
if (($handle = fopen($csvFilePath, 'r')) !== false) {
// Create an XMLWriter instance
/* You cant write the Station element until you have read the csv file
as it needs data for its properties from there
So moved inside the while loop
*/
$xmlWriter = new XMLWriter();
$xmlWriter->openURI(csvFileToXmlFile($csvFile));
$xmlWriter->startDocument('1.0', 'UTF-8');
$flagFirstLineWritten = false; // control writing on Station element only once
while (($data = fgetcsv($handle,10000,';')) !== false) {
// Skip empty lines
if (count($data) === 0) {
continue;
}
/*
output the Station element with its properties only once
*/
if ( ! $flagFirstLineWritten ) {
$xmlWriter->startElement('Station');
$xmlWriter->writeAttribute('id', $data[4]);
$xmlWriter->writeAttribute('name', $data[17]);
$xmlWriter->writeAttribute('geocode', $data[18]);
$xmlWriter->endAttribute();
$flagFirstLineWritten = true;
}
// Ensure the array has the necessary indexes
if (count($data) >= 4) {
// Extract the necessary data
/*
convert the DATE to a timestamp
*/
$ts = (new DateTime())->createFromFormat( DateTimeInterface::ISO8601, $data[0]);
// Check if the attribute has a value
if (trim($data[3]) !== '') {
// Start XML record element
$xmlWriter->startElement('rec');
$xmlWriter->writeAttribute('ts', (string)$ts->getTimestamp());
$xmlWriter->writeAttribute('nox', $data[1]);
$xmlWriter->writeAttribute('no', $data[2]);
$xmlWriter->writeAttribute('no2', $data[3]);
// End XML record element
$xmlWriter->endElement(); // end rec
}
}
}
$xmlWriter->endElement(); // station element
$xmlWriter->endDocument();
$xmlWriter->flush();
fclose($handle);
// Output success message
$xmlFile = csvFileToXmlFile($csvFile);
echo "XML file generated successfully: $xmlFile\n";
}
}
// Function to convert CSV file name to XML file name
function csvFileToXmlFile($csvFile) {
$fileParts = pathinfo($csvFile);
$xmlFile = $fileParts['filename'] . '.xml';
return $xmlFile;
}
RESULTS, example
<?xml version="1.0" encoding="UTF-8"?>
<Station id="203" name="Brislington Depot" geocode="51.441747180510106, -2.5599558321904605">
<rec ts="1546326000" nox="18.5" no="12.5" no2="3.75"/>
<rec ts="1546412400" nox="163.75" no="55.0" no2="71.0"/>
. . .
. . .
</Station>