pull:初次提交

This commit is contained in:
Yep_Q
2025-09-08 04:48:28 +08:00
parent 5c0619656d
commit f64f498365
11751 changed files with 1953723 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
{
"node": "n8n-nodes-base.xml",
"nodeVersion": "1.0",
"codexVersion": "1.0",
"categories": ["Core Nodes"],
"resources": {
"primaryDocumentation": [
{
"url": "https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.xml/"
}
],
"generic": [
{
"label": "What are APIs and how to use them with no code",
"icon": " 🪢",
"url": "https://n8n.io/blog/what-are-apis-how-to-use-them-with-no-code/"
}
]
},
"alias": ["Parse"],
"subcategories": {
"Core Nodes": ["Data Transformation"]
}
}

View File

@@ -0,0 +1,300 @@
import type {
IExecuteFunctions,
INodeExecutionData,
INodeType,
INodeTypeDescription,
} from 'n8n-workflow';
import { NodeConnectionTypes, NodeOperationError, deepCopy } from 'n8n-workflow';
import { Builder, Parser } from 'xml2js';
export class Xml implements INodeType {
description: INodeTypeDescription = {
displayName: 'XML',
name: 'xml',
icon: 'fa:file-code',
iconColor: 'purple',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["mode"]==="jsonToxml" ? "JSON to XML" : "XML to JSON"}}',
description: 'Convert data from and to XML',
defaults: {
name: 'XML',
color: '#333377',
},
inputs: [NodeConnectionTypes.Main],
outputs: [NodeConnectionTypes.Main],
properties: [
{
displayName: 'Mode',
name: 'mode',
type: 'options',
options: [
{
name: 'JSON to XML',
value: 'jsonToxml',
description: 'Converts data from JSON to XML',
},
{
name: 'XML to JSON',
value: 'xmlToJson',
description: 'Converts data from XML to JSON',
},
],
default: 'xmlToJson',
description: 'From and to what format the data should be converted',
},
{
displayName:
"If your XML is inside a binary file, use the 'Extract from File' node to convert it to text first",
name: 'xmlNotice',
type: 'notice',
default: '',
displayOptions: {
show: {
mode: ['xmlToJson'],
},
},
},
// ----------------------------------
// option:jsonToxml
// ----------------------------------
{
displayName: 'Property Name',
name: 'dataPropertyName',
type: 'string',
displayOptions: {
show: {
mode: ['jsonToxml'],
},
},
default: 'data',
required: true,
description: 'Name of the property to which to contains the converted XML data',
},
{
displayName: 'Options',
name: 'options',
type: 'collection',
placeholder: 'Add option',
displayOptions: {
show: {
mode: ['jsonToxml'],
},
},
default: {},
options: [
{
displayName: 'Allow Surrogate Chars',
name: 'allowSurrogateChars',
type: 'boolean',
default: false,
description: 'Whether to allow using characters from the Unicode surrogate blocks',
},
{
displayName: 'Attribute Key',
name: 'attrkey',
type: 'string',
default: '$',
description: 'Prefix that is used to access the attributes',
},
{
displayName: 'Cdata',
name: 'cdata',
type: 'boolean',
default: false,
description:
'Whether to wrap text nodes in <![CDATA[ ... ]]> instead of escaping when necessary. Does not add <![CDATA[ ... ]]> if it is not required.',
},
{
displayName: 'Character Key',
name: 'charkey',
type: 'string',
default: '_',
description: 'Prefix that is used to access the character content',
},
{
displayName: 'Headless',
name: 'headless',
type: 'boolean',
default: false,
description: 'Whether to omit the XML header',
},
{
displayName: 'Root Name',
name: 'rootName',
type: 'string',
default: 'root',
description: 'Root element name to be used',
},
],
},
// ----------------------------------
// option:xmlToJson
// ----------------------------------
{
displayName: 'Property Name',
name: 'dataPropertyName',
type: 'string',
displayOptions: {
show: {
mode: ['xmlToJson'],
},
},
default: 'data',
required: true,
description: 'Name of the property which contains the XML data to convert',
},
{
displayName: 'Options',
name: 'options',
type: 'collection',
placeholder: 'Add option',
displayOptions: {
show: {
mode: ['xmlToJson'],
},
},
default: {},
options: [
{
displayName: 'Attribute Key',
name: 'attrkey',
type: 'string',
default: '$',
description: 'Prefix that is used to access the attributes',
},
{
displayName: 'Character Key',
name: 'charkey',
type: 'string',
default: '_',
description: 'Prefix that is used to access the character content',
},
{
displayName: 'Explicit Array',
name: 'explicitArray',
type: 'boolean',
default: false,
description:
'Whether to always put child nodes in an array if true; otherwise an array is created only if there is more than one',
},
{
displayName: 'Explicit Root',
name: 'explicitRoot',
type: 'boolean',
default: true,
description:
'Whether to set this if you want to get the root node in the resulting object',
},
{
displayName: 'Ignore Attributes',
name: 'ignoreAttrs',
type: 'boolean',
default: false,
description: 'Whether to ignore all XML attributes and only create text nodes',
},
{
displayName: 'Merge Attributes',
name: 'mergeAttrs',
type: 'boolean',
default: true,
description:
'Whether to merge attributes and child elements as properties of the parent, instead of keying attributes off a child attribute object. This option is ignored if ignoreAttrs is true.',
},
{
displayName: 'Normalize',
name: 'normalize',
type: 'boolean',
default: false,
description: 'Whether to trim whitespaces inside text nodes',
},
{
displayName: 'Normalize Tags',
name: 'normalizeTags',
type: 'boolean',
default: false,
description: 'Whether to normalize all tag names to lowercase',
},
{
displayName: 'Trim',
name: 'trim',
type: 'boolean',
default: false,
description: 'Whether to trim the whitespace at the beginning and end of text nodes',
},
],
},
],
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData();
const mode = this.getNodeParameter('mode', 0) as string;
const dataPropertyName = this.getNodeParameter('dataPropertyName', 0);
const options = this.getNodeParameter('options', 0, {});
let item: INodeExecutionData;
const returnData: INodeExecutionData[] = [];
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
try {
item = items[itemIndex];
if (mode === 'xmlToJson') {
const parserOptions = Object.assign(
{
mergeAttrs: true,
explicitArray: false,
},
options,
);
const parser = new Parser(parserOptions);
if (item.json[dataPropertyName] === undefined) {
throw new NodeOperationError(
this.getNode(),
`Item has no JSON property called "${dataPropertyName}"`,
{ itemIndex },
);
}
const json = await parser.parseStringPromise(item.json[dataPropertyName] as string);
returnData.push({ json: deepCopy(json) });
} else if (mode === 'jsonToxml') {
const builder = new Builder(options);
returnData.push({
json: {
[dataPropertyName]: builder.buildObject(items[itemIndex].json),
},
pairedItem: {
item: itemIndex,
},
});
} else {
throw new NodeOperationError(this.getNode(), `The operation "${mode}" is not known!`, {
itemIndex,
});
}
} catch (error) {
if (this.continueOnFail()) {
items[itemIndex] = {
json: {
error: error.message,
},
pairedItem: {
item: itemIndex,
},
};
continue;
}
throw error;
}
}
return [returnData];
}
}

View File

@@ -0,0 +1,5 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
describe('Test XML Node', () => {
new NodeTestHarness().setupTests();
});

View File

@@ -0,0 +1,134 @@
{
"name": "My workflow",
"nodes": [
{
"parameters": {},
"id": "7f04c09e-5a60-4a0c-a336-ef38e4732452",
"name": "When clicking \"Execute Workflow\"",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [860, 380]
},
{
"parameters": {
"jsCode": "return [\n {\n json: {\n a: {\n b: {\n c: 1\n }\n }\n }\n }\n];\n"
},
"id": "be80ce82-d312-460d-ac79-05c0626845ad",
"name": "Code",
"type": "n8n-nodes-base.code",
"typeVersion": 1,
"position": [1080, 380]
},
{
"parameters": {
"mode": "jsonToxml",
"options": {}
},
"id": "c352655b-e0dc-4f7c-a63a-ff1bc5f1909f",
"name": "XML",
"type": "n8n-nodes-base.xml",
"typeVersion": 1,
"position": [1300, 380]
},
{
"parameters": {
"options": {}
},
"id": "21547e44-133e-4c3b-a601-0cffba1daf9b",
"name": "XML1",
"type": "n8n-nodes-base.xml",
"typeVersion": 1,
"position": [1500, 380]
},
{
"parameters": {
"values": {
"string": [
{
"name": "new",
"value": "={{ $json.a }}"
}
]
},
"options": {}
},
"id": "632dee22-10d1-424d-b1d2-673b95b32943",
"name": "Set",
"type": "n8n-nodes-base.set",
"typeVersion": 2,
"position": [1720, 380]
}
],
"pinData": {
"Set": [
{
"json": {
"a": {
"b": {
"c": "1"
}
},
"new": {
"b": {
"c": "1"
}
}
}
}
]
},
"connections": {
"When clicking \"Execute Workflow\"": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
}
]
]
},
"Code": {
"main": [
[
{
"node": "XML",
"type": "main",
"index": 0
}
]
]
},
"XML": {
"main": [
[
{
"node": "XML1",
"type": "main",
"index": 0
}
]
]
},
"XML1": {
"main": [
[
{
"node": "Set",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {},
"versionId": "14c1d4b8-3546-4692-8e8a-44c244c79bcc",
"id": "0G78Fh2FTnM46kuR",
"meta": {
"instanceId": "021d3c82ba2d3bc090cbf4fc81c9312668bcc34297e022bb3438c5c88a43a5ff"
},
"tags": []
}

View File

@@ -0,0 +1,148 @@
{
"name": "xml tests",
"nodes": [
{
"parameters": {},
"id": "745d1191-f221-4eda-9d09-611233f97edd",
"name": "When clicking \"Execute Workflow\"",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [460, 520]
},
{
"parameters": {
"mode": "jsonToxml",
"options": {}
},
"id": "fb48ca4c-5ae2-4c57-9ca9-2080d06dbf65",
"name": "XML",
"type": "n8n-nodes-base.xml",
"typeVersion": 1,
"position": [960, 280]
},
{
"parameters": {
"jsCode": "return {\n data: {\n id: 1,\n firstName: 'Adam',\n secondName: 'Smith',\n fullName: 'Adam Smith',\n }\n}"
},
"id": "6a04ca32-c9cc-4cb1-a6b9-3a505b1c2dd5",
"name": "Code",
"type": "n8n-nodes-base.code",
"typeVersion": 1,
"position": [700, 400]
},
{
"parameters": {
"mode": "jsonToxml",
"options": {
"headless": true
}
},
"id": "cd740e65-5117-4bec-a3b3-6863ba25f232",
"name": "XML1",
"type": "n8n-nodes-base.xml",
"typeVersion": 1,
"position": [960, 500]
},
{
"parameters": {
"jsCode": "return {\n\"data\":\n'<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?> <data> <id>1</id> <firstName>Adam</firstName> <secondName>Smith</secondName> <fullName>Adam Smith</fullName> </data>'\n}"
},
"id": "817afbf7-9342-403f-8dc0-c4a3905fde4d",
"name": "Code1",
"type": "n8n-nodes-base.code",
"typeVersion": 1,
"position": [680, 640]
},
{
"parameters": {
"options": {}
},
"id": "f0f37a8f-9136-42e8-be34-f32b77e4aa88",
"name": "XML2",
"type": "n8n-nodes-base.xml",
"typeVersion": 1,
"position": [940, 700]
}
],
"pinData": {
"XML": [
{
"json": {
"data": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<data>\n <id>1</id>\n <firstName>Adam</firstName>\n <secondName>Smith</secondName>\n <fullName>Adam Smith</fullName>\n</data>"
}
}
],
"XML1": [
{
"json": {
"data": "<data>\n <id>1</id>\n <firstName>Adam</firstName>\n <secondName>Smith</secondName>\n <fullName>Adam Smith</fullName>\n</data>"
}
}
],
"XML2": [
{
"json": {
"data": {
"id": "1",
"firstName": "Adam",
"secondName": "Smith",
"fullName": "Adam Smith"
}
}
}
]
},
"connections": {
"When clicking \"Execute Workflow\"": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
},
{
"node": "Code1",
"type": "main",
"index": 0
}
]
]
},
"Code": {
"main": [
[
{
"node": "XML",
"type": "main",
"index": 0
},
{
"node": "XML1",
"type": "main",
"index": 0
}
]
]
},
"Code1": {
"main": [
[
{
"node": "XML2",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {},
"versionId": "c1fde9d5-f27c-4e62-bc5c-8be787dcc227",
"id": "109",
"meta": {
"instanceId": "36203ea1ce3cef713fa25999bd9874ae26b9e4c2c3a90a365f2882a154d031d0"
},
"tags": []
}