C# to Cache objects
I am trying to achieve this in cache objects I am using 2014.1 here is the original code in C# and would like to convert this to cache
here is my code first c# and cache follows
class Program
{
/// <summary>
/// This function loads a XML document from the specified string.
/// </summary>
/// <param name="xml">Input XML string</param>
/// <returns>XML to Json converted string</returns>
public static string XmlToJSON(string xml)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
StringBuilder sbJSON = new StringBuilder();
sbJSON.Append("{ ");
XmlToJSONnode(sbJSON, xmlDoc.DocumentElement, true);
sbJSON.Append("}");
return sbJSON.ToString();
}
/// <summary>
/// Output a XmlElement, possibly as part of a higher array
/// </summary>
/// <param name="sbJSON">Json string to be created</param>
/// <param name="node">XML node name</param>
/// <param name="showNodeName">ArrayList of string or XmlElement</param>
private static void XmlToJSONnode(StringBuilder sbJSON, XmlElement node,
bool showNodeName)
{
if (showNodeName)
{
sbJSON.Append("\"" + SafeJSON(node.Name) + "\": ");
}
sbJSON.Append("{");
// Building 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(" }");
}
/// <summary>
/// Store data associated with each nodeName so that we know whether
/// the nodeName is an array or not.
/// </summary>
/// <param name="childNodeNames">Collection of child nodes</param>
/// <param name="nodeName">XML node name</param>
/// <param name="nodeValue">XML node value</param>
private static void StoreChildNode(SortedList<string, object> childNodeNames,
string nodeName, object nodeValue)
{
// Pre-process contraction of XmlElements.
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);
}
/// <summary>
/// This functions outputs all the stored information inside a child node.
/// </summary>
/// <param name="childname">Chile node name</param>
/// <param name="alChild">Child node</param>
/// <param name="sbJSON">Json string</param>
/// <param name="showNodeName">Node visibility</param>
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(", ");
}
/// <summary>
/// This function makes a string safe for JSON.
/// </summary>
/// <param name="sIn">Input child node</param>
/// <returns>String safe Json</returns>
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();
}
/// <summary>
/// This function converts Json string to XML
/// </summary>
/// <param name="json">Inout Json string</param>
/// <returns>Converted XML string</returns>
public static XmlDocument JsonToXml(string json)
{
XmlNode newNode = null;
XmlNode appendToNode = null;
string[] arrElementData;
XmlDocument returnXmlDoc = new XmlDocument();
returnXmlDoc.LoadXml("<menu />");
XmlNode rootNode = returnXmlDoc.SelectSingleNode("menu");
appendToNode = rootNode;
string[] arrElements = json.Split('\r');
foreach (string element in arrElements)
{
string processElement = element.Replace("\r", "").Replace("\n", "").Replace("\t", "").Trim();
if ((processElement.IndexOf("}") > -1 || processElement.IndexOf("]") > -1) &&
appendToNode != rootNode)
{
appendToNode = appendToNode.ParentNode;
}
else if (processElement.IndexOf("[") > -1)
{
processElement = processElement.Replace(":", "").Replace("[", "").Replace("\"", "").Trim();
newNode = returnXmlDoc.CreateElement(processElement);
appendToNode.AppendChild(newNode);
appendToNode = newNode;
}
else if (processElement.IndexOf("{") > -1 && processElement.IndexOf(":") > -1)
{
processElement = processElement.Replace(":", "").Replace("{", "").Replace("\"", "").Trim();
newNode = returnXmlDoc.CreateElement(processElement);
appendToNode.AppendChild(newNode);
appendToNode = newNode;
}
else
{
if (processElement.IndexOf(":") > -1)
{
arrElementData = processElement.Replace(": \"", ":").Replace("\",", "").Replace("\"", "").Split(':');
newNode = returnXmlDoc.CreateElement(arrElementData[0]);
for (int i = 1; i < arrElementData.Length; i++)
{ newNode.InnerText += arrElementData[i]; }
appendToNode.AppendChild(newNode);
}
}
}
return returnXmlDoc;
}
static void Main(string[] args)
{
string xml = "<menu id=\"file\" value=\"File\"> " +
"<popup>" +
"<menuitem value=\"New\" onclick=\"CreateNewDoc()\" />" +
"<menuitem value=\"Open\" onclick=\"OpenDoc()\" />" +
"<menuitem value=\"Close\" onclick=\"CloseDoc()\" />" +
"</popup>" +
"</menu>";
Console.WriteLine("Input XML string:\n");
Console.WriteLine(xml);
Console.WriteLine("\nOutput JSON string:\n");
Console.WriteLine(XmlToJSON(xml));
Console.WriteLine("\n================================================================================\n");
const string json = @"{
""foo"":""bar"",
""complexFoo"": {
""subFoo"":""subBar""
}
}";
Console.WriteLine("Input JSON string:\n");
Console.WriteLine(json);
Console.WriteLine("\nOutput XML string:\n");
Console.WriteLine(JsonToXml(json).InnerXml);
Console.WriteLine();
}
}
Class SharpJSONToXML Extends %RegisteredObject
{
///<summary>
/// This functions loads a xml stream from a specified file
/// <param name="myfile">input xml file
Method LoadXMLFile(myfile As %String = "C:\test2.xml") As %Stream
{
// open a text file using a %Library.File stream
Set file = ##class(%File).%New(myfile)
Do file.Open("RU") // same flags as the OPEN command
nbsp; // and copy the file into Memo
Set incomeStream =##class(%Stream.FileCharacter).%New()
Do incomeStream.CopyFrom(file)
nbsp; Set file = "" // close the file
Do ..XmlToJSON(incomeStream)
return incomeStream
}
<summary>
/// This function loads a XML stream.
/// </summary>
/// <param name="xml">Input XML stream</param>
/// <returns>XML to Json converted stream</returns>
Method XmlToJSON(xml As %Stream) As %Stream
{
set xmlDoc =##class(%XML.TextReader).ParseStream(xml,.textreader)
set sbJSON =##class(%Stream.FileCharacter).%New()
do sbJSON.WriteLine($C(123))
do ..XmlToJSONnode(sbJSON,textreader.Name,1)
do sbJSON.writeLine($C(125))
return sbJSON
}
<summary>
/// Output a XmlElement, possibly as part of a higher array
/// </summary>
/// <param name="sbJSON">Json string to be created</param>
/// <param name="node">XML node name</param>
/// <param name="showNodeName">ArrayList of string or XmlElement</param>
Method XmlToJSONnode(sbJSON As %AbstractStream, node As %XML.Document, showNodeName As %Boolean)
{
if (showNodeName)
{
do sbJSON.WriteLine($C(92)_..SafeJSON(node.GetDocumentNode())_$C(92)_$C(58))
}
do sbJSON.WriteLine($C(123))
// Building 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.
Set childNodeNames =##class(%ListOfObjects).%New()
// Add in all node attributes.
For tI=1:1:node.Count()
{
Set tResult=node.GetAt(tI)
if (tResult.HasAttributes)
{
For tJ=1:1:tResult.AttributeCount
{
Do tResult.MoveToAttributeIndex(tJ)
do ..StoreChildNode(childNodeNames, tResult.Name, tResult.Value)
}
}
// Add in all nodes.
if tResult.HasChildNodes()
{
if (tResult.Name){do ..StoreChildNode(childNodeNames,tResult.Name, tI) }elseif (tResult.Value){ do ..StoreChildNode(childNodeNames, "value",tResult.Value)}
}
}
// Now output all stored info.
for childname=1:1:childNodeNames
{
#dim alChild as %ListOfObjects
if (alChild.Count = 1)
{
do ..OutputNode(childname, alChild, sbJSON,1)
}
else
{
do sbJSON.WriteLine($C(92)_..SafeJSON(childname)_$C(92)_$C(58)_$C(91))
for tm=1:1: alChild
{
do ..OutputNode(childname, Child, sbJSON,0)
do sbJSON.Remove(sbJSON.Length - 2, 2)
do sbJSON.WriteLine($C(93)_$C(44))
}
}
}
do sbJSON.Remove(sbJSON.Length - 2, 2)
do sbJSON.WriteLine($C(125))
}
/// <summary>
/// Store data associated with each nodeName so that we know whether
/// the nodeName is an array or not.
/// </summary>
/// <param name="childNodeNames">Collection of child nodes</param>
/// <param name="nodeName">XML node name</param>
/// <param name="nodeValue">XML node value</param>
Method StoreChildNode(childNodeNames As %ListOfObjects(CLASSNAME="%XML.XPATH.Result"), nodeName As %String, nodeValue As %XML.Node)
{
// Pre-process contraction of XmlElements.
if (nodeValue.NodeType="Element")
{
// Convert <aa></aa> into "aa":null
// <aa>xx</aa> into "aa":"xx".
#dim cnode As %XML.Node
#dim children As %XML.Node
if (cnode.Attributes.Count = 0)
{
set children = cnode.HasChildNodes()
if (children.Count = 0)
{
}
elseif (children.Count = 1)
{
}
}
}
// Add nodeValue to ArrayList associated with each nodeName.
// If nodeName doesn't exist then add it.
#dim ValuesAL as %ListOfObjects
if (childNodeNames.ContainsKey(nodeName))
{
set ValuesAL = childNodeNames
}
else
{
set childNodeNames = ValuesAL
}
set ValuesAL=$LISTBUILD(nodeValue)
}
/// <summary>
/// This functions outputs all the stored information inside a child node.
/// </summary>
/// <param name="childname">Chile node name</param>
/// <param name="alChild">Child node</param>
/// <param name="sbJSON">Json string</param>
/// <param name="showNodeName">Node visibility</param>
Method OutputNode(childname As %String, alChild As %RegisteredObject, sbJSON As %Stream, showNodeName As %Boolean)
{
if (alChild = null)
{
if (showNodeName)
{
do sbJSON.WriteLine($C(92)_..SafeJSON(childname)_$C(92)_$C(58))
}
do sbJSON.WriteLine("null")
}
elseif (alChild)
{
if (showNodeName)
{
do sbJSON.WriteLine($C(92)_..SafeJSON(childname)_$C(92)_$C(58))
}
set sChild = alChild
set sChild = TRIM("")
do sbJSON.writeLine($C(92)_..SafeJSON(sChild)_$C(92))
}
else
{
do ..XmlToJSONnode(sbJSON,alChild, showNodeName)
}
do sbJSON.WriteLine($C(4))
/// <summary>
/// This function makes a string safe for JSON.
/// </summary>
/// <param name="sIn">Input child node</param>
/// <returns>String safe Json</returns>
Method SafeJSON(sIn As %XML.Node) As %Stream
{
Set sbOut = ##class(%Stream.FileCharacter).%New()
for i=1:1:sIn
{
if ($C(60) || $C(92)_$C(62))
{
continue
}
elseif ($C(92)_$C(34) || $C(92)_$C(92) || $C(47))
{
do sbOut.write($C(92)_$C(92))
}
do sbOut.write()
}
return sbOut
}
}
And what's your question ?
so far when I run my code in cache I get this error <INVALID OREF>zXmlToJSONnode+3^SharpJSONToXML.1 and I would like to know the equivalent in cache for that method if you look at it
@Robert.Cemper
sbJSON that actually get passed to XmlToJSONNode is not an object. Additionally try this modification to XmlToJSON (you need to specify file if you want to use file stream):
I was wondering where this goes and how you could get so far.
Caché uses a temp file.
USER>zw sc
sc=1
USER>zw sbJSON
sbJSON=<OBJECT REFERENCE>[6@%Stream.FileCharacter]
+----------------- general information ---------------
| oref value: 6
| class name: %Stream.FileCharacter
| reference count: 2
+----------------- attribute values ------------------
| (%Concurrency) = 1
| %Location = "" <Set>
| (%LockRef) = ""
| (%Locked) = 0
| AtEnd = 0
| BOM = ""
| (CurrFile) = "C:\InterSystems\17E20\mgr\Temp\mAiLCZXuPXOaSQ.stream"
| Id = "" <Set>
| LineTerminator = $c(13,10) <Set>
| (MakePermLoc) = 1
| (Mode) = 3
|(NormalizedDirectory) = "C:\InterSystems\17E20\mgr\Temp\"
|(OidTranslateTable) = 0
| (ReadMode) = 0
| ReadSize = ""
| RemoveOnClose = 0
| (StoreFile) = ""
| StreamFormatWrite = 1
| (TempFile) = "mAiLCZXuPXOaSQ.stream"
| TranslateTable = "" <Set>
| UseVMSVersion = 0
| (VariableRecord) = 0
+--------------- calculated references ---------------
| CanonicalFilename <Get>
| Filename <Get,Set>
| LastModified <Get>
| Size <Get>
+-----------------------------------------------------
USER>
that's is the only way I could do it have any suggestion on how I can Improve that thank you
@Robert.Cemper
you should ensure that in the last else branch in method ..OutputNode() your variable
alChild is an object of type %XML.Document to satify your method
.. XmlToJSONnode(sbJSON As %AbstractStream, node As %XML.Document, showNodeName As %Boolean)
when you call it.
Object are always passed by reference.
Analyzing you code I see the problem in this line:
I take for given that sbJSON is a valid object.
So I further investigate on node
#1 from ..
#2 is suspicious as in .. OutputNode() I see
{
if (alChild = null) // EMPTY, NOT AN OBJECT
{ ... }
elseif (alChild) // IT IS eventually an OBJECT REFERENCE
{ ... }
else // NOT EMPTY, NOT NUMERIC, AND NOT AN OBJECT REFERENCE
{
do ..XmlToJSONnode(sbJSON,alChild, showNodeName)
; > > > > > > > > > > > > > > > > > > > >^^^^^^ // WHAT is this now ???
}
do sbJSON.WriteLine($C(4))
}
so what you hand over is not an oref as this looks like <integer>@<classname>
therefore you fail with <INVALID OREF>zXmlToJSONnode+3^SharpJSONToXML.1
so some action is required to find out what happens
BTW:
passing sbJSON by reference would make this recursive construct easier to understand
as you intend to work to the same stream object anyhow.
or just use %sbJSON as single common reference