diff --git a/packages/backend/src/services/xmlService.ts b/packages/backend/src/services/xmlService.ts index 6a8dcc3..06608ee 100644 --- a/packages/backend/src/services/xmlService.ts +++ b/packages/backend/src/services/xmlService.ts @@ -32,15 +32,18 @@ const buildXmlNode = (node: any): any => { export const streamToXml = async (res: any) => { console.log('Starting streamToXml function...'); - // Write XML header (compact like Rekordbox) - res.write(''); - res.write(''); + // Write XML header with encoding (like master collection) + res.write(''); + res.write('\n\n'); + + // Add PRODUCT section + res.write('\n '); // Start COLLECTION section console.log('Counting songs in database...'); const songCount = await Song.countDocuments(); console.log(`Found ${songCount} songs in database`); - res.write(''); + res.write(`\n `); // Stream songs in batches to avoid memory issues const batchSize = 100; @@ -53,18 +56,25 @@ export const streamToXml = async (res: any) => { .lean(); for (const song of songs) { - // Only include TrackID, Name, and Artist like Rekordbox - res.write(``); + // Include ALL track attributes like master collection + res.write(`\n `); + + // Add TEMPO entries if they exist + if (song.tempo) { + res.write(`\n `); + } + + res.write('\n '); } processedSongs += songs.length; console.log(`Streamed ${processedSongs}/${songCount} songs...`); } - res.write(''); + res.write('\n '); // Start PLAYLISTS section - res.write(''); + res.write('\n '); // Stream playlists console.log('Fetching playlists from database...'); @@ -72,19 +82,47 @@ export const streamToXml = async (res: any) => { console.log(`Found ${playlists.length} playlists in database`); // Write ROOT node with correct Count - res.write(``); + res.write(`\n `); for (const playlist of playlists) { - await streamPlaylistNodeCompact(res, playlist); + await streamPlaylistNodeFull(res, playlist); } - res.write(''); - res.write(''); - res.write(''); + res.write('\n '); + res.write('\n '); + res.write('\n'); res.end(); }; +const streamPlaylistNodeFull = async (res: any, node: any) => { + const nodeType = node.type === 'folder' ? '0' : '1'; + + if (node.type === 'folder') { + const childCount = node.children ? node.children.length : 0; + res.write(`\n `); + + if (node.children && node.children.length > 0) { + for (const child of node.children) { + await streamPlaylistNodeFull(res, child); + } + } + + res.write('\n '); + } else { + const trackCount = node.tracks ? node.tracks.length : 0; + res.write(`\n `); + + if (node.tracks && node.tracks.length > 0) { + for (const trackId of node.tracks) { + res.write(`\n `); + } + } + + res.write('\n '); + } +}; + const streamPlaylistNodeCompact = async (res: any, node: any) => { const nodeType = node.type === 'folder' ? '0' : '1';