Files
xCommons/Helpers/XMLToJSONHelper.cs
T
2024-01-25 04:39:39 +03:30

178 lines
5.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
namespace xCommons.Helpers {
public partial class XMLToJSONHelper {
//
#region Actions ...
public static string ToJSON (string xml) {
//
XmlDocument doc = new XmlDocument ();
doc.LoadXml (xml);
//
return XmlToJSON (doc);
}
public static string XmlToJSON (XmlDocument xmlDoc) {
//
StringBuilder sbJSON = new StringBuilder ();
//
sbJSON.Append ("{ ");
XmlToJSONnode (sbJSON, xmlDoc.DocumentElement, true);
sbJSON.Append ("}");
//
return sbJSON.ToString ();
}
#endregion
//
#region Private ...
//
private static void XmlToJSONnode (StringBuilder sbJSON, XmlElement node, bool showNodeName) {
//
if (showNodeName) {
sbJSON.Append ("\"" + SafeJSON (node.Name) + "\": ");
}
//
sbJSON.Append ("{");
//
// Build a sorted list of key-value pairs
// where key is case-sensitive nodeName
// value is an ArrayList of string or XmlElement
// so that we know whether the nodeName is an array or not.
SortedList<string, object> childNodeNames = new SortedList<string, object> ();
//
// Add in all node attributes
if (node.Attributes != null)
foreach (XmlAttribute attr in node.Attributes)
StoreChildNode (childNodeNames, attr.Name, attr.InnerText);
//
// Add in all nodes
foreach (XmlNode cnode in node.ChildNodes) {
//
if (cnode is XmlText) {
StoreChildNode (childNodeNames, "value", cnode.InnerText);
} else if (cnode is XmlElement) {
StoreChildNode (childNodeNames, cnode.Name, cnode);
}
}
//
// Now output all stored info
foreach (string childname in childNodeNames.Keys) {
//
List<object> alChild = (List<object>) childNodeNames[childname];
if (alChild.Count == 1) {
OutputNode (childname, alChild[0], sbJSON, true);
} else {
//
sbJSON.Append (" \"" + SafeJSON (childname) + "\": [ ");
//
foreach (object Child in alChild) {
OutputNode (childname, Child, sbJSON, false);
}
//
sbJSON.Remove (sbJSON.Length - 2, 2);
sbJSON.Append (" ], ");
}
}
//
sbJSON.Remove (sbJSON.Length - 2, 2);
sbJSON.Append (" }");
}
//
// StoreChildNode: Store data associated with each nodeName
// so that we know whether the nodeName is an array or not.
private static void StoreChildNode (SortedList<string, object> childNodeNames, string nodeName, object nodeValue) {
//
// Pre-process contraction of XmlElement-s
if (nodeValue is XmlElement) {
//
// Convert <aa></aa> into "aa":null
// <aa>xx</aa> into "aa":"xx"
XmlNode cnode = (XmlNode) nodeValue;
if (cnode.Attributes.Count == 0) {
//
XmlNodeList children = cnode.ChildNodes;
if (children.Count == 0) {
nodeValue = null;
} else if (children.Count == 1 && (children[0] is XmlText)) {
nodeValue = ((XmlText) (children[0])).InnerText;
}
}
}
//
// Add nodeValue to ArrayList associated with each nodeName
// If nodeName doesn't exist then add it
List<object> ValuesAL;
//
if (childNodeNames.ContainsKey (nodeName)) {
ValuesAL = (List<object>) childNodeNames[nodeName];
} else {
//
ValuesAL = new List<object> ();
childNodeNames[nodeName] = ValuesAL;
}
//
ValuesAL.Add (nodeValue);
}
//
private static void OutputNode (string childname, object alChild, StringBuilder sbJSON, bool showNodeName) {
if (alChild == null) {
if (showNodeName)
sbJSON.Append ("\"" + SafeJSON (childname) + "\": ");
sbJSON.Append ("null");
} else if (alChild is string) {
if (showNodeName)
sbJSON.Append ("\"" + SafeJSON (childname) + "\": ");
string sChild = (string) alChild;
sChild = sChild.Trim ();
sbJSON.Append ("\"" + SafeJSON (sChild) + "\"");
} else
XmlToJSONnode (sbJSON, (XmlElement) alChild, showNodeName);
sbJSON.Append (", ");
}
//
// Make a string safe for JSON
private static string SafeJSON (string sIn) {
//
StringBuilder sbOut = new StringBuilder (sIn.Length);
foreach (char ch in sIn) {
//
if (Char.IsControl (ch) || ch == '\'') {
//
int ich = (int) ch;
sbOut.Append (@"\u" + ich.ToString ("x4"));
continue;
} else if (ch == '\"' || ch == '\\' || ch == '/') {
sbOut.Append ('\\');
}
//
sbOut.Append (ch);
}
//
return sbOut.ToString ();
}
#endregion
}
}