Files
ukaiautomation/tools/data-converter.php

320 lines
15 KiB
PHP
Raw Normal View History

<?php
$page_title = "Free Data Format Converter | JSON CSV XML | UK AI Automation";
$page_description = "Convert between JSON, CSV, and XML formats instantly. Free online tool for data transformation - no signup required.";
$canonical_url = "https://ukaiautomation.co.uk/tools/data-converter";
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo htmlspecialchars($page_title); ?></title>
<meta name="description" content="<?php echo htmlspecialchars($page_description); ?>">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@100;200;300;400;500;600;700;800;900&family=Lato:wght@100;200;300;400;500;600;700;800;900&display=swap" rel="stylesheet">
<link rel="canonical" href="<?php echo htmlspecialchars($canonical_url); ?>">
<meta property="og:title" content="<?php echo htmlspecialchars($page_title); ?>">
<meta property="og:description" content="<?php echo htmlspecialchars($page_description); ?>">
<link rel="stylesheet" href="../assets/css/main.css?v=20260222">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "Data Format Converter",
"description": "Free tool to convert between JSON, CSV, and XML data formats",
"url": "https://ukaiautomation.co.uk/tools/data-converter",
"applicationCategory": "BusinessApplication",
"operatingSystem": "Web Browser",
"offers": { "@type": "Offer", "price": "0", "priceCurrency": "GBP" }
}
</script>
<style>
.converter-container { max-width: 1100px; margin: 0 auto; padding: 40px 20px; }
.converter-header { text-align: center; margin-bottom: 40px; }
.converter-header h1 { font-size: 2.2em; color: #1e1b4b; margin-bottom: 15px; }
.converter-header p { color: #666; font-size: 1.1em; }
.converter-card { background: #fff; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.08); padding: 30px; }
.format-selector { display: flex; justify-content: center; gap: 15px; margin-bottom: 25px; flex-wrap: wrap; align-items: center; }
.format-btn { padding: 12px 24px; border: 2px solid #e0e0e0; border-radius: 8px; background: white; cursor: pointer; font-weight: 600; transition: all 0.2s; }
.format-btn:hover { border-color: #6d28d9; }
.format-btn.active { background: #6d28d9; color: white; border-color: #6d28d9; }
.arrow { font-size: 1.5em; color: #888; }
.editor-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
@media (max-width: 768px) { .editor-grid { grid-template-columns: 1fr; } }
.editor-box { display: flex; flex-direction: column; }
.editor-box label { font-weight: 600; color: #1e1b4b; margin-bottom: 10px; display: flex; justify-content: space-between; align-items: center; }
.editor-box textarea { flex: 1; min-height: 350px; padding: 15px; border: 2px solid #e0e0e0; border-radius: 8px; font-family: 'Monaco', 'Menlo', monospace; font-size: 0.9em; resize: vertical; }
.editor-box textarea:focus { border-color: #6d28d9; outline: none; }
.btn-row { display: flex; justify-content: center; gap: 15px; margin: 25px 0; flex-wrap: wrap; }
.btn { padding: 14px 28px; border: none; border-radius: 8px; font-weight: 600; cursor: pointer; transition: all 0.2s; }
.btn-primary { background: #6d28d9; color: white; }
.btn-primary:hover { background: #148a72; }
.btn-secondary { background: #f5f5f5; color: #333; border: 2px solid #e0e0e0; }
.btn-secondary:hover { background: #e8e8e8; }
.copy-btn { padding: 6px 12px; font-size: 0.85em; background: #f0f0f0; border: none; border-radius: 4px; cursor: pointer; }
.copy-btn:hover { background: #e0e0e0; }
.error-msg { background: #ffebee; color: #c62828; padding: 12px; border-radius: 6px; margin-top: 15px; display: none; }
.success-msg { background: #e8f5e9; color: #2e7d32; padding: 12px; border-radius: 6px; margin-top: 15px; display: none; }
.breadcrumb { padding: 15px 20px; background: #f5f5f5; font-size: 0.9em; }
.breadcrumb a { color: #7c3aed; text-decoration: none; }
.breadcrumb span { color: #888; margin: 0 8px; }
.sample-data { font-size: 0.85em; color: #666; margin-top: 8px; }
.sample-data a { color: #6d28d9; cursor: pointer; text-decoration: underline; }
</style>
</head>
<body>
<?php include($_SERVER["DOCUMENT_ROOT"] . "/includes/nav.php"); ?>
<nav class="breadcrumb">
<a href="/">Home</a> <span></span> <a href="/tools/">Tools</a> <span></span> Data Converter
</nav>
<div class="converter-container">
<div class="converter-header">
<h1>🔄 Data Format Converter</h1>
<p>Convert between JSON, CSV, and XML formats instantly. Your data stays in your browser.</p>
</div>
<div class="converter-card">
<div class="format-selector">
<div>
<strong>From:</strong>
<button class="format-btn active" data-format="json" onclick="setInputFormat('json')">JSON</button>
<button class="format-btn" data-format="csv" onclick="setInputFormat('csv')">CSV</button>
<button class="format-btn" data-format="xml" onclick="setInputFormat('xml')">XML</button>
</div>
<span class="arrow"></span>
<div>
<strong>To:</strong>
<button class="format-btn" data-output="json" onclick="setOutputFormat('json')">JSON</button>
<button class="format-btn active" data-output="csv" onclick="setOutputFormat('csv')">CSV</button>
<button class="format-btn" data-output="xml" onclick="setOutputFormat('xml')">XML</button>
</div>
</div>
<div class="editor-grid">
<div class="editor-box">
<label>
<span>📥 Input (<span id="inputFormatLabel">JSON</span>)</span>
<button class="copy-btn" onclick="clearInput()">Clear</button>
</label>
<textarea id="inputData" placeholder="Paste your data here..."></textarea>
<div class="sample-data">
Try sample: <a onclick="loadSample()">Load example data</a>
</div>
</div>
<div class="editor-box">
<label>
<span>📤 Output (<span id="outputFormatLabel">CSV</span>)</span>
<button class="copy-btn" onclick="copyOutput()">Copy</button>
</label>
<textarea id="outputData" readonly placeholder="Converted data will appear here..."></textarea>
</div>
</div>
<div class="btn-row">
<button class="btn btn-primary" onclick="convert()">🔄 Convert</button>
<button class="btn btn-secondary" onclick="downloadOutput()">⬇️ Download</button>
</div>
<div id="errorMsg" class="error-msg"></div>
<div id="successMsg" class="success-msg"></div>
</div>
<div style="margin-top: 40px; padding: 30px; background: #f8f9fa; border-radius: 12px;">
<h3 style="color: #1e1b4b; margin-bottom: 15px;">💡 About This Tool</h3>
<p style="color: #666; line-height: 1.7;">
This free converter handles common data transformations needed when working with web scraped data:
</p>
<ul style="color: #666; margin-top: 15px; padding-left: 20px; line-height: 1.8;">
<li><strong>JSON CSV</strong> Perfect for opening scraped data in Excel or Google Sheets</li>
<li><strong>CSV JSON</strong> Convert spreadsheet data to API-friendly format</li>
<li><strong>XML JSON/CSV</strong> Transform legacy XML feeds into modern formats</li>
</ul>
<p style="color: #666; margin-top: 15px;">
<strong>Privacy:</strong> All conversions happen in your browser. Your data never leaves your device.
</p>
</div>
</div>
<?php include '../includes/footer.php'; ?>
<script>
let inputFormat = 'json';
let outputFormat = 'csv';
function setInputFormat(format) {
inputFormat = format;
document.querySelectorAll('[data-format]').forEach(b => b.classList.remove('active'));
document.querySelector(`[data-format="${format}"]`).classList.add('active');
document.getElementById('inputFormatLabel').textContent = format.toUpperCase();
}
function setOutputFormat(format) {
outputFormat = format;
document.querySelectorAll('[data-output]').forEach(b => b.classList.remove('active'));
document.querySelector(`[data-output="${format}"]`).classList.add('active');
document.getElementById('outputFormatLabel').textContent = format.toUpperCase();
}
function loadSample() {
const samples = {
json: `[
{"name": "Product A", "price": 29.99, "category": "Electronics"},
{"name": "Product B", "price": 49.99, "category": "Home"},
{"name": "Product C", "price": 19.99, "category": "Electronics"}
]`,
csv: `name,price,category
Product A,29.99,Electronics
Product B,49.99,Home
Product C,19.99,Electronics`,
xml: `<?xml version="1.0"?>
<products>
<product><name>Product A</name><price>29.99</price><category>Electronics</category></product>
<product><name>Product B</name><price>49.99</price><category>Home</category></product>
<product><name>Product C</name><price>19.99</price><category>Electronics</category></product>
</products>`
};
document.getElementById('inputData').value = samples[inputFormat];
}
function clearInput() {
document.getElementById('inputData').value = '';
document.getElementById('outputData').value = '';
hideMessages();
}
function hideMessages() {
document.getElementById('errorMsg').style.display = 'none';
document.getElementById('successMsg').style.display = 'none';
}
function showError(msg) {
hideMessages();
document.getElementById('errorMsg').textContent = '❌ ' + msg;
document.getElementById('errorMsg').style.display = 'block';
}
function showSuccess(msg) {
hideMessages();
document.getElementById('successMsg').textContent = '✅ ' + msg;
document.getElementById('successMsg').style.display = 'block';
}
function convert() {
const input = document.getElementById('inputData').value.trim();
if (!input) { showError('Please enter some data to convert'); return; }
try {
let data;
// Parse input
if (inputFormat === 'json') {
data = JSON.parse(input);
if (!Array.isArray(data)) data = [data];
} else if (inputFormat === 'csv') {
data = csvToArray(input);
} else if (inputFormat === 'xml') {
data = xmlToArray(input);
}
// Convert to output
let output;
if (outputFormat === 'json') {
output = JSON.stringify(data, null, 2);
} else if (outputFormat === 'csv') {
output = arrayToCsv(data);
} else if (outputFormat === 'xml') {
output = arrayToXml(data);
}
document.getElementById('outputData').value = output;
showSuccess(`Converted ${data.length} records from ${inputFormat.toUpperCase()} to ${outputFormat.toUpperCase()}`);
} catch (e) {
showError('Conversion failed: ' + e.message);
}
}
function csvToArray(csv) {
const lines = csv.split('\n').filter(l => l.trim());
const headers = lines[0].split(',').map(h => h.trim());
return lines.slice(1).map(line => {
const values = line.split(',');
const obj = {};
headers.forEach((h, i) => obj[h] = values[i]?.trim() || '');
return obj;
});
}
function arrayToCsv(arr) {
if (!arr.length) return '';
const headers = Object.keys(arr[0]);
const rows = arr.map(obj => headers.map(h => {
let val = obj[h] || '';
if (val.toString().includes(',')) val = `"${val}"`;
return val;
}).join(','));
return [headers.join(','), ...rows].join('\n');
}
function xmlToArray(xml) {
const parser = new DOMParser();
const doc = parser.parseFromString(xml, 'text/xml');
const items = doc.querySelectorAll(doc.documentElement.tagName + ' > *');
return Array.from(items).map(item => {
const obj = {};
Array.from(item.children).forEach(child => {
obj[child.tagName] = child.textContent;
});
return obj;
});
}
function arrayToXml(arr) {
if (!arr.length) return '<?xml version="1.0"?>\n<data></data>';
let xml = '<?xml version="1.0"?>\n<data>\n';
arr.forEach(obj => {
xml += ' <item>\n';
Object.entries(obj).forEach(([k, v]) => {
xml += ` <${k}>${escapeXml(v)}</${k}>\n`;
});
xml += ' </item>\n';
});
xml += '</data>';
return xml;
}
function escapeXml(str) {
return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}
function copyOutput() {
const output = document.getElementById('outputData');
output.select();
document.execCommand('copy');
showSuccess('Copied to clipboard!');
}
function downloadOutput() {
const output = document.getElementById('outputData').value;
if (!output) { showError('Nothing to download'); return; }
const ext = outputFormat === 'json' ? 'json' : outputFormat === 'csv' ? 'csv' : 'xml';
const mime = outputFormat === 'json' ? 'application/json' : outputFormat === 'csv' ? 'text/csv' : 'text/xml';
const blob = new Blob([output], { type: mime });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `converted-data.${ext}`;
a.click();
URL.revokeObjectURL(url);
}
</script>
</body>
</html>