@bindujoseph yeah something like this. I just used AI for this and didn't change much, but it highlights what you could do. You could also have a more simple script that just runs the replace statements, where that gives you valid XML, then you send that valid XML to another flow.
Input:
{
"data": [
{
"text": "<?xml version=\"1.0\" encoding=\"utf-8\"?>OFF-SITE WORK KITSet Includes #2953 Wireless Charging Mouse Pad With Phone Stand, #1343 Jotter With Sticky Notes And Flags, #1333 - 3-Tier Stationary Set, #2496 3-In-1 Xoopar Octo-Charging Cables, #224 .5 Oz. Screen Cleaner And Spray\n<br />\n<br />\n<br />\n As low as 35.49 each @450 qty.<br />MPC1908off-site-work-kitproduct.simpleproduct.xml.config40FalseFalseFalseFalseTrueFalseFalseFalseTrueFalseFalse0<Variant <span>\n<h2></h2>\n</span>1173535.490000.500000099991TrueFalseFalse0TrueFalseFalse1-10False"
}
],
"errors": [],
"_exportId": "66ce7e1bf7c3628b407d80fc",
"_connectionId": "63628238e6dfe03093953a68",
"_flowId": "66ce7e1b3a88959f61a68f04",
"pageIndex": 0,
"settings": {
"integration": {},
"flowGrouping": {},
"flow": {},
"export": {},
"connection": {},
"iClient": {}
},
"testMode": true
}
Output:
{
"data": [
{
"text": "<?xml version=\"1.0\" encoding=\"utf-8\"?>OFF-SITE WORK KITSet Includes #2953 Wireless Charging Mouse Pad With Phone Stand, #1343 Jotter With Sticky Notes And Flags, #1333 - 3-Tier Stationary Set, #2496 3-In-1 Xoopar Octo-Charging Cables, #224 .5 Oz. Screen Cleaner And Spray\n
\n
\n
\n As low as 35.49 each @450 qty.
MPC1908off-site-work-kitproduct.simpleproduct.xml.config40FalseFalseFalseFalseTrueFalseFalseFalseTrueFalseFalse0<Variant \n\n1173535.490000.500000099991TrueFalseFalse0TrueFalseFalse1-10False",
"parsed": {
"?xml": {
"@attributes": {
"version": "1.0",
"encoding": "utf-8"
}
},
"Description": [
{},
{}
],
"SKU": "MPC1908",
"SE": [
{},
{}
],
"ProductType": {
"@attributes": {
"Name": "Generic Product",
"ID": "1",
"GUID": "b60e6a65-ec2a-4fca-8f16-029bb03729cc"
}
},
"ColWidth": "4",
"SkinID": "0",
"Images": [
{},
{}
],
"UpsellProducts": {
"@attributes": {
"DiscountPercentage": "0.0000"
}
},
"InventoryType": {},
"IsAKit": "False",
"IsSystem": "False",
"ShowBuyButton": "False",
"Published": [
"True",
"True"
],
"Wholesale": [
"False",
"False"
],
"RequiresRegistration": "False",
"HidePriceUntilCart": "False",
"IsCallToOrder": "True",
"ExcludeFromPriceFeeds": "False",
"RequiresTextOption": "False",
"TextOptionMaxLength": "0",
"StoreMappings": {
"@attributes": {
"AutoCleanup": "true"
}
},
"Mappings": {
"@attributes": {
"AutoCleanup": "true"
}
},
"Variants": {
"@attributes": {
"AutoCleanup": "true"
}
},
"ProductID": "11735",
"Price": "35.4900",
"SalePrice": "0",
"Weight": "0.5000",
"MSRP": "0",
"Cost": "0",
"Points": "0",
"Inventory": "9999",
"DisplayOrder": "1",
"IsTaxable": "True",
"IsShipSeparately": "False",
"IsDownload": "False",
"FreeShipping": "0",
"IsRecurring": "False",
"RecurringInterval": "1",
"RecurringIntervalType": "-1",
"MinimumQuantity": "0",
"CustomerEntersPrice": "False"
}
}
],
"errors": [],
"abort": false,
"newErrorsAndRetryData": []
}
Script:
function preSavePage(options) {
for (let d of options.data) {
if (d.text && typeof d.text === 'string') {
// Replace HTML entities and preserve new lines
d.text = d.text.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/'/g, "'")
.replace(/\\n/g, '\n'); // Replace escaped newline characters with actual newlines
// Convert the decoded XML string to a JSON object
d.parsed = xmlToJson(d.text);
} else {
console.error('Warning: d.text is undefined or not a string.');
}
}
return {
data: options.data,
errors: options.errors,
abort: false,
newErrorsAndRetryData: []
};
}
function xmlToJson(xml) {
const parseXmlNode = (node) => {
let obj = {};
const nodeNameMatch = node.match(/^<([^\s/>]+)(.*?)>/);
if (!nodeNameMatch) return obj;
const tagName = nodeNameMatch[1];
const attributes = nodeNameMatch[2].trim();
const attrObj = {};
attributes.replace(/(\w+)="(.*?)"/g, (_, key, value) => {
attrObj[key] = value;
});
const innerXml = node.substring(nodeNameMatch[0].length, node.lastIndexOf(``));
if (innerXml.trim()) {
obj[tagName] = innerXml.includes('<') ? xmlToJson(innerXml) : innerXml;
}
if (Object.keys(attrObj).length > 0) {
obj[tagName] = { ...obj[tagName], "@attributes": attrObj };
}
return obj;
};
const result = {};
const nodes = xml.match(/<[^/][^>]*>.*?<\/[^>]+>/gs) || [];
nodes.forEach(node => {
const parsedNode = parseXmlNode(node);
const key = Object.keys(parsedNode)[0];
if (result[key]) {
if (!Array.isArray(result[key])) {
result[key] = [result[key]];
}
result[key].push(parsedNode[key]);
} else {
result[key] = parsedNode[key];
}
});
return result;
}