I\'m trying to store user-input in an XML document on the client-side (javascript), and transmit that to the server for persistence.
One user, for example, pasted i
Here's a function sanitizeStringForXML() which can either be used to cleanse strings before assignment, or a derivative function removeInvalidCharacters(xmlNode) which can be passed a DOM tree and will automatically sanitize attributes and textNodes so they are safe to store.
var stringWithSTX = "Bad" + String.fromCharCode(2) + "News";
var xmlNode = $("<myelem/>").attr("badattr", stringWithSTX);
var serializer = new XMLSerializer();
var invalidXML = serializer.serializeToString(xmlNode);
// Now cleanse it:
removeInvalidCharacters(xmlNode);
var validXML = serializer.serializeToString(xmlNode);
I based this on a list of characters from the non-restricted characters section of this wikipedia article, but the supplementary planes require 5-hex-digit unicode characters, and the Javascript regex does not include a syntax for this, so for now, I'm just stripping them out (you aren't missing too much...):
// WARNING: too painful to include supplementary planes, these characters (0x10000 and higher)
// will be stripped by this function. See what you are missing (heiroglyphics, emoji, etc) at:
// http://en.wikipedia.org/wiki/Plane_(Unicode)#Supplementary_Multilingual_Plane
var NOT_SAFE_IN_XML_1_0 = /[^\x09\x0A\x0D\x20-\xFF\x85\xA0-\uD7FF\uE000-\uFDCF\uFDE0-\uFFFD]/gm;
function sanitizeStringForXML(theString) {
"use strict";
return theString.replace(NOT_SAFE_IN_XML_1_0, '');
}
function removeInvalidCharacters(node) {
"use strict";
if (node.attributes) {
for (var i = 0; i < node.attributes.length; i++) {
var attribute = node.attributes[i];
if (attribute.nodeValue) {
attribute.nodeValue = sanitizeStringForXML(attribute.nodeValue);
}
}
}
if (node.childNodes) {
for (var i = 0; i < node.childNodes.length; i++) {
var childNode = node.childNodes[i];
if (childNode.nodeType == 1 /* ELEMENT_NODE */) {
removeInvalidCharacters(childNode);
} else if (childNode.nodeType == 3 /* TEXT_NODE */) {
if (childNode.nodeValue) {
childNode.nodeValue = sanitizeStringForXML(childNode.nodeValue);
}
}
}
}
}
Note that this only removes invalid characters from nodeValues of attributes and textNodes. It does not check tag names or attribute names, comments, etc etc.
Check https://gist.github.com/john-doherty/b9195065884cdbfd2017a4756e6409cc,
very useful gist, example usage:
const resultXml = removeXMLInvalidChars(INPUT_XML_STRING, true);