UNPKG

n8n-nodes-xml-plus

Version:

An alternative XML node based on fast-xml-parser as opposed to xml2js that's used in the built-in XML node. Designed for performance with larger datasets as well as adding additional customizability.

235 lines 10.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.XmlPlus = void 0; const n8n_workflow_1 = require("n8n-workflow"); const fast_xml_parser_1 = require("fast-xml-parser"); const XmlPlusOptions_1 = require("./XmlPlusOptions"); class XmlPlus { constructor() { this.description = { displayName: 'XML Plus', name: 'xmlPlus', description: 'Convert data to and from XML (community node)', icon: 'file:XmlPlus.svg', group: [], version: 1, defaults: { name: 'XML Plus', }, inputs: ["main"], outputs: ["main"], properties: [{ displayName: 'Operation', name: 'operation', description: 'The conversion needed for the input data', type: 'options', default: 'xmlToJson', noDataExpression: true, options: [{ name: 'JSON to XML', value: 'jsonToXml', description: 'Converts data from JSON to XML', action: 'Convert JSON to XML', }, { name: 'XML to JSON', value: 'xmlToJson', description: 'Converts data from XML to JSON', action: 'Convert XML to JSON', }, { name: 'Validate XML', value: 'validateOnly', description: 'Validates XML without conversion', action: 'Validate XML', }, ], }, { displayName: 'Use Entire JSON', name: 'useEntireJson', description: "Whether to use the full incoming JSON or the 'Input Property'", type: 'boolean', default: false, displayOptions: { show: { operation: ['jsonToXml'], }, }, }, { displayName: 'Input Property', name: 'inputProperty', description: 'Name of the property to be converted', type: 'string', default: 'data', required: true, requiresDataPath: 'single', displayOptions: { hide: { useEntireJson: [true], }, }, }, { displayName: 'Output Property', name: 'outputProperty', description: 'Name of the output property where the converted data will be stored', type: 'string', default: 'data', required: true, requiresDataPath: 'single', }, { displayName: 'Format XML', name: 'format', description: 'Whether parsed XML is output as a single-line XML string or formatted using tabs and newlines', type: 'boolean', default: true, displayOptions: { show: { operation: ['jsonToXml'], }, }, }, { displayName: 'Validator', name: 'validateXml', description: 'Whether to enable or disable XML validation on the parsed or built XML data', type: 'boolean', default: false, }, ...XmlPlusOptions_1.xmlPlusOptions, ], }; } async execute() { const items = this.getInputData(); const operation = this.getNodeParameter('operation', 0); const returnData = []; for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { try { const item = items[itemIndex]; const jsonData = item.json; const outputProperty = this.getNodeParameter('outputProperty', itemIndex); const validateXml = this.getNodeParameter('validateXml', itemIndex); function getNestedProperty(obj, path) { return path.split('.').reduce((acc, key) => acc === null || acc === void 0 ? void 0 : acc[key], obj); } if (operation === 'xmlToJson') { const inputProperty = this.getNodeParameter('inputProperty', itemIndex); const xmlString = getNestedProperty(jsonData, inputProperty); const parserOptions = this.getNodeParameter('parserOptions', itemIndex, {}); const validatorOptions = this.getNodeParameter('validatorOptions', itemIndex, {}); if (xmlString === undefined) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Item has no JSON property named "${inputProperty}"`, { itemIndex }); } const parser = new fast_xml_parser_1.XMLParser({ ignoreAttributes: false, ...parserOptions }); const json = parser.parse(xmlString); if (validateXml) { const validation = fast_xml_parser_1.XMLValidator.validate(xmlString, validatorOptions); if (validation !== true) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid XML: ${validation.err.msg}`, { itemIndex }); } } returnData.push({ json: { [outputProperty]: json, }, pairedItem: { item: itemIndex, }, }); } else if (operation === 'jsonToXml') { const parserOptions = this.getNodeParameter('parserOptions', itemIndex, {}); const useEntireJson = this.getNodeParameter('useEntireJson', itemIndex); const format = this.getNodeParameter('format', itemIndex); const includeXmlDeclaration = parserOptions === null || parserOptions === void 0 ? void 0 : parserOptions.includeXmlDeclaration; const xmlDeclarationType = parserOptions === null || parserOptions === void 0 ? void 0 : parserOptions.xmlDeclarationType; const validatorOptions = this.getNodeParameter('validatorOptions', itemIndex, {}); const builder = new fast_xml_parser_1.XMLBuilder({ ignoreAttributes: false, suppressBooleanAttributes: false, format, ...parserOptions }); let xml; if (useEntireJson) { xml = builder.build(jsonData); } else { const inputProperty = this.getNodeParameter('inputProperty', itemIndex); xml = builder.build(jsonData[inputProperty]); } if (validateXml) { const validation = fast_xml_parser_1.XMLValidator.validate(xml, validatorOptions); if (validation !== true) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Built XML is invalid: ${validation.err.msg}`, { itemIndex }); } } if (includeXmlDeclaration) { let declaration = ''; switch (xmlDeclarationType) { case 'version11': declaration = '<?xml version="1.1" encoding="UTF-8"?>\n'; break; case 'noEncoding': declaration = '<?xml version="1.0"?>\n'; break; case 'standard': default: declaration = '<?xml version="1.0" encoding="UTF-8"?>\n'; } xml = declaration + xml; } returnData.push({ json: { [outputProperty]: xml, }, pairedItem: { item: itemIndex, }, }); } else if (operation === 'validateOnly') { const inputProperty = this.getNodeParameter('inputProperty', itemIndex); const xmlString = getNestedProperty(item.json, inputProperty); const validatorOptions = this.getNodeParameter('validatorOptions', itemIndex, {}); const validation = fast_xml_parser_1.XMLValidator.validate(xmlString, validatorOptions); returnData.push({ json: { [outputProperty]: { valid: validation === true, message: validation === true ? 'XML is valid' : validation.err.msg, }, }, pairedItem: { item: itemIndex }, }); } } catch (error) { if (error instanceof n8n_workflow_1.NodeOperationError) { throw error; } throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown error occurred: ${error.message || error}`, { itemIndex }); } } return [returnData]; } } exports.XmlPlus = XmlPlus; //# sourceMappingURL=XmlPlus.node.js.map