I wrote the following function to do this job.
Works pretty well when collections (arrays) inside your object are named with "s" suffix (as plurals for their content).
function serializeNestedNodeXML(xmlDoc, parentNode, newNodeName, obj) {
if (Array.isArray(obj)) {
var xmlArrayNode = xmlDoc.createElement(newNodeName);
parentNode.appendChild(xmlArrayNode);
obj.forEach(function (e) {
serializeNestedNodeXML(xmlDoc, xmlArrayNode, newNodeName.substring(0, newNodeName.length - 1), e)
});
return; // Do not process array properties
} else if (obj) {
var objType = typeof obj;
switch (objType) {
case 'string': case 'number': case 'boolean':
parentNode.setAttribute(newNodeName, obj)
break;
case 'object':
var xmlProp = xmlDoc.createElement(newNodeName);
parentNode.appendChild(xmlProp);
for (var prop in obj) {
serializeNestedNodeXML(xmlDoc, xmlProp, prop, obj[prop]);
}
break;
}
}
}
And I invoked it this way (as a function of the serialized class itself):
this.serializeToXML = function () {
var xmlDoc = document.implementation.createDocument(null, "YourXMLRootNodeName", null);
serializeNestedNodeXML(xmlDoc, xmlDoc.documentElement, 'YourSerializedClassName', this);
var serializer = new XMLSerializer();
return serializer.serializeToString(xmlDoc);
}
But an hour later I moved to JSON...