// Import the parseString function from xml-reader import XmlReader from 'xml-reader'; // Define the structure of an XML node interface XMLNode { name: string; attributes: { [key: string]: string }; children: XMLNode[]; value?: string; }; // Define the structure of our parsed result interface ParsedResult { xmlString: string; parsed: XMLNode; }; /** * complete xml * * @param partialXml * @returns */ export const completeXML = (partialXml: string): string => { // Regular expressions to match opening and closing tags const openTagsRegex = /<([^\/\s>]+)[^>]*>/g; const closeTagsRegex = /<\/([^>]+)>/g; const openTags: string[] = []; // match let match; // Find all opening tags while ((match = openTagsRegex.exec(partialXml)) !== null) { openTags.push(match[1]); } // Remove tags that are already closed while ((match = closeTagsRegex.exec(partialXml)) !== null) { const index = openTags.lastIndexOf(match[1]); if (index !== -1) { openTags.splice(index, 1); } } // Close remaining open tags let completedXml = partialXml; for (let i = openTags.length - 1; i >= 0; i--) { completedXml += ``; } // return completed xml return completedXml; }; // Function to parse a single XML string export const parseXML = (xmlString: string, withComplete: boolean = false): XMLNode|undefined => { // try/catch try { // complete if (withComplete) { return XmlReader.parseSync(completeXML(xmlString)); } // new promise return XmlReader.parseSync(xmlString); } catch (e) {} }; // Main function to extract and parse XML blocks from a message export const extractXMLBlocks = (message: string, withComplete: boolean = true): ParsedResult[] => { // Regular expression to match XML-like structures const xmlRegex = /<(\w+)[\s\S]*?<\/\1>/g; // finish regex if (withComplete) { // complete xml message = completeXML(message); } // Find all potential XML matches in the message const xmlMatches = message.match(xmlRegex) || []; // Array to store successfully parsed results const parsedBlocks: ParsedResult[] = []; // Iterate through each potential XML match for (const xmlString of xmlMatches) { try { // Attempt to parse the XML string const parsed = parseXML(xmlString); // check parsed if (!parsed) continue; // If successful, add both the original string and parsed result to the array parsedBlocks.push({ xmlString, parsed }); } catch (error) { // If parsing fails, log the error but continue with the next match console.error(`Error parsing XML block: ${error}`); } } // Return the array of successfully parsed results return parsedBlocks; }; /** * extract blocks */ export default extractXMLBlocks;