which references the defunct json2xml node and trying to replace it with the xml node as recommended by @DaveCJ
while
var messageObj = {"Response": { "Say": "Welcome to Node-Red."}};
results in valid TwiML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Response><Say>Welcome to Node-Red.</Say></Response>
something more complicated adds extraneous characters for array elements like <0> <0/> etc that twilio barfs on
In the end I just removed the xml node altogether and just formatted the TwiML as a literal string to send back as the response
Hope this helps someone else who needs to mess with TwilioIVR
[{"id":"6a16e094.95e92","type":"inject","z":"fce70880.0318f8","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":222,"y":291,"wires":[["99750490.668af8"]]},{"id":"6163845a.9e9c7c","type":"http response","z":"fce70880.0318f8","name":"Send TwiML","x":662,"y":165,"wires":[]},{"id":"cfd36806.302c98","type":"http in","z":"fce70880.0318f8","name":"TwilioVoice incoming","url":"/twiliovoice","method":"post","x":105,"y":248,"wires":[["99750490.668af8","fe3c68ac.01c398"]]},{"id":"99750490.668af8","type":"function","z":"fce70880.0318f8","name":"Process Call","func":"// Create JSON object for payload response\n/*\nvar messageObj = { \"Gather\": [{ \"@\": { \"action\": \"http://1.2.3.4:8080/twilioivr\",\"numDigits\":\"1\"},\n\t\t \"Say\": [ { \"@\": { \"voice\": \"woman\" }, \"#\": \"Welcome to Node-Red. For power usage press 1. To ring the bell press 2. For anything else press 3\" }]}],\n\t\t \"Say\": [ { \"@\": { \"voice\": \"woman\" }, \"#\": \"You didnt press a key, goodbye\"}]};\n*/\n//var messageObj = {\"Response\": { \"Say\": \"Welcome to Node-Red.\"}};\n\n/* The sort of example XML we are trying to create is shown below:\n\n <Gather action=\"handle-user-input.php\" numDigits=\"1\">\n <Say>Welcome to TPS.</Say>\n <Say>For store hours, press 1.</Say>\n <Say>To speak to an agent, press 2.</Say>\n <Say>To check your package status, press 3.</Say>\n </Gather>\n <!-- If customer doesn't input anything, prompt and try again. -->\n <Say>Sorry, I didn't get your response.</Say>\n*/\n\nvar twiml_response = \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"yes\\\"?> \\\n <Response> \\\n <Gather action=\\\"http://1.2.3.4:8080/twilioivr\\\" numDigits=\\\"1\\\"> \\\n <Say voice=\\\"woman\\\">Welcome to Node-Red. For power usage press 1. To ring the bell press 2. For anything else press 3</Say> \\\n </Gather> \\\n <Say voice=\\\"woman\\\">Sorry, I didn't get your response.</Say> \\\n </Response>\";\nmsg.payload = twiml_response;\nreturn msg;","outputs":1,"noerr":0,"x":417,"y":249,"wires":[["6163845a.9e9c7c","82e22444.7d1dd8"]]},{"id":"12a09218.ed5f6e","type":"http in","z":"fce70880.0318f8","name":"TwilioVoice Handle","url":"/twilioivr","method":"post","x":109,"y":328,"wires":[["14ee455a.eb11bb","faabe843.055418"]]},{"id":"82e22444.7d1dd8","type":"debug","z":"fce70880.0318f8","name":"","active":true,"complete":false,"x":654,"y":293,"wires":[]},{"id":"14ee455a.eb11bb","type":"debug","z":"fce70880.0318f8","name":"","active":true,"complete":false,"x":406,"y":394,"wires":[]},{"id":"fe3c68ac.01c398","type":"debug","z":"fce70880.0318f8","name":"","active":false,"console":false,"complete":"payload","x":414,"y":182,"wires":[]},{"id":"faabe843.055418","type":"function","z":"fce70880.0318f8","name":"handleGather","func":"var digit = msg.payload.Digits;\n\nresponseMsg = \"You pressed \" + digit;\n\n\nvar twiml_response = \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"yes\\\"?> \\\n <Response> \\\n <Say voice=\\\"woman\\\">\" + responseMsg + \"</Say> \\\n </Response>\";\nmsg.payload = twiml_response;\nreturn msg;","outputs":1,"noerr":0,"x":421,"y":323,"wires":[["6163845a.9e9c7c","82e22444.7d1dd8"]]}]
If anyone has a nicer TwiML flow, please publish your flow