
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
12-04-2018 06:51 PM
Hi,
I'm trying to convert XML strings to JSON objects using gs.xmlToJSON()
I've found that if the XML contains a character entity such as then the conversion fails.
For example
var xTest = "<a>Hello World</a>";
var obj = gs.xmlToJSON(xTest);
// obj is null;
var xmlDoc = new XMLDocument2();
xmlDoc.parseXML(xTest);
var tOrF = xmlDoc.isValid();
// tOrF is true
I know that the XML is valid because the XMLDocument2.isValid() method is OK.
I also know that if I take out the & in then the conversion works.
var xTest = "<a>Hello World</a>";
xTest = "<a>Hello #13; World</a>";
var obj = gs.xmlToJSON(xTest);
// obj is an Object.
Has anyone seen this problem? Is there a work around?
Any help is appreciated.
Thanks,
Cody
Solved! Go to Solution.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
12-05-2018 01:55 PM
Hi Simon,
Thanks for the suggestions! However, I'm not able to use the XMLHelper because I'm in a scoped application.
It seems that the gs.xmlToJSON() command should work because is a valid character entity. It appears all over the payload of ecc_queue records.
I decided to go a "kludgy" route and strip out the white space characters that are common. To that end I created a script include that converts Xml to Json and that converts Json To XML. The Json to XML part, I copied from the XMLHelper Script include from ServiceNow.
Below is the content of the script include. It's called OkXMLHelper because ... it's OK for what I need!
When it comes to converting Xml to JSON. There are differences between how this works and how XMLHelper works. I've documented the differences in the description of the Script Include which I've attached to this comment. Along, with a scheduled job for testing.
var OkXMLHelper = Class.create();
OkXMLHelper.prototype = {
initialize : function() {
},
toObject : function(s){
this.toObject = function(s){
s = this.fixXml(s);
var obj = gs.xmlToJSON(s);
return obj;
};
this.fixXml = function(s){
//The gs.xmlToJSON() method doesn't handle character entities.
//So I'm replacing the common ones for whitespace characters that appear
//in the ecc_queue payload strings that I'm primarily working with.
if(s.match(/&#/ig) != null){
s = s.replace(/ /ig, "\r");
s = s.replace(/ /ig, "\n");
if(s.match(/&#/ig) == null){
return s;
}
s = s.replace(/	/ig, "\t");
s = s.replace(/	/ig, "\t");
}
return s;
};
return this.toObject(s);
},
toXMLStr : function(o, leaveBlanks) {
/*
This was copied from the XMLHelper script include provided by ServiceNow.
*/
var toXml = function(v, name, ind) {
if (typeof(v) == "function")
return "";
var xml = "";
if (v instanceof Array) {
for ( var i = 0, n = v.length; i < n; i++)
xml += ind + toXml(v[i], name, ind + "\t") + "\n";
} else if (typeof (v) == "object") {
var hasChild = false;
xml += ind + "<" + name;
for ( var m in v) {
if (m.charAt(0) == "@")
xml += " " + m.substr(1) + "=\"" + v[m].toString() + "\"";
else
hasChild = true;
}
xml += hasChild ? ">" : "/>";
if (hasChild) {
for ( var m in v) {
if (m == "#text")
xml += v[m];
else if (m == "#cdata")
xml += "<![CDATA[" + v[m] + "]]>";
else if (m.charAt(0) != "@")
xml += toXml(v[m], m, ind + "\t");
}
xml += (xml.charAt(xml.length - 1) == "\n" ? ind : "") + "</" + name + ">";
}
} else {
xml += ind + "<" + name + ">" + v.toString() + "</" + name + ">";
}
return xml;
};
xml = "";
for ( var m in o)
xml += toXml(o[m], m, "");
if (leaveBlanks)
return xml;
return xml.replace(/\t|\n/g, "");
},
type : "OkXMLHelper"
};
Also if you are interested in running a scheduled job in the debugger, which is what I used for testing this, see Test Scheduled Jobs(and Fix Scripts) in the Script Debugger
Thanks,
Cody
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-25-2021 01:04 AM
When you are on scoped app, your solution is, by far, the best.
Thanks for sharing it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-08-2024 04:48 AM
try
var XmlToJson = Class.create();
XmlToJson.prototype = {
initialize: function() {},
convert: function(xml) {
var xmlDoc = new XMLDocument2();
xmlDoc.parseXML(xml);
var root = xmlDoc.getDocumentElement();
if (!root) {
gs.error("Root element is null. Unable to parse XML.");
return null;
}
var jsonResult = {};
jsonResult[root.getNodeName()] = this.parseXmlToJson(root);
return jsonResult;
},
isEmptyObject: function(obj) {
return Object.keys(obj).length === 0;
},
parseXmlToJson: function(node) {
if (!node) return null; // Check if node is null
var jsonObject = {};
// Get attributes (if any) with a null check
var attrs = node.getAttributes();
if (!this.isEmptyObject(attrs)) {
jsonObject = attrs;
}
// Iterate through child nodes
var childNodes = node.getChildNodeIterator();
if (childNodes.hasNext()) {
while (childNodes.hasNext()) {
var childNode = childNodes.next();
var childName = childNode.getNodeName();
var childValue = childNode.getNodeValue();
// Skip text nodes
if (childName === "#text") {
if (!this.isEmptyObject(attrs)) {
jsonObject['value'] = childValue || null;
} else {
jsonObject = childValue || null;
}
continue;
};
if (childNode.isCDATANode()) {
jsonObject[childName] = childValue;
} else if (!jsonObject[childName]) {
jsonObject[childName] = this.parseXmlToJson(childNode);
} else {
// Handle cases where there are multiple nodes with the same name
if (!Array.isArray(jsonObject[childName])) {
jsonObject[childName] = [jsonObject[childName]];
}
jsonObject[childName].push(this.parseXmlToJson(childNode));
}
}
} else if (this.isEmptyObject(attrs)) {
// If there are no child nodes, get the node's value
jsonObject = node.getNodeValue() || null;
}
return jsonObject;
},
type: 'XmlToJson'
};
var xml = "XML paylod";
gs.info(JSON.stringify(new XmlToJson().convert(xml), null, 2))