XMLReader option for Cerbuino Bee

My search shows that the Cerbuino does not support XmlReader.
I looked at JSON and it scared me (a bit over my head).
Can anyone suggest an option to XmlReader?

I’m a hack programmer so still trying to start with code that does 90% of what I need.

I just need to move the contents of an XML file to a searchable array.

Any hints would be appreciated.

Thanks, Keith

XML legacy DLL should work on cerb

I changed to the legacy library and …

I get the following and don’t know quite how to debug this.
(Note: I also found this bit of info. that may be related to the issue I am having: http://netmf.codeplex.com/workitem/1054)

An unhandled exception of type ‘System.OutOfMemoryException’ occurred in System.Xml.Legacy.dll

Occurs at this line:
xmlr.Read();

When running the code cpied from this page: https://www.ghielectronics.com/docs/32/xml

Which is copy and pasted from my program here:

  #region XML writer and reader
        public void myXMLwriter()
        {
            MemoryStream ms = new MemoryStream();
            XmlWriter xmlwrite = XmlWriter.Create(ms);

            xmlwrite.WriteProcessingInstruction("xml",
                  "version=\"1.0\" encoding=\"utf-8\"");
            xmlwrite.WriteComment("This is just a comment");
            xmlwrite.WriteStartElement("NETMF_DataLogger");//root element
            xmlwrite.WriteStartElement("FileName");//child element
            xmlwrite.WriteString("Data");
            xmlwrite.WriteEndElement();
            xmlwrite.WriteStartElement("FileExt");
            xmlwrite.WriteString("txt");
            xmlwrite.WriteEndElement();
            xmlwrite.WriteStartElement("SampleFeq");
            xmlwrite.WriteString("10");
            xmlwrite.WriteEndElement();
            xmlwrite.WriteEndElement();//end the root element

            //xmlwrite.WriteString("<test>data</test>");

            xmlwrite.Flush();
            xmlwrite.Close();
            //////// display the XML data ///////////
            byte[] byteArray = ms.ToArray();
            char[] cc = System.Text.UTF8Encoding.UTF8.GetChars(byteArray);
            string str = new string(cc);
            Debug.Print(str);
            ms.Flush();
            ms.Close();

            ///////////read xml
            MemoryStream rms = new MemoryStream(byteArray);

            XmlReaderSettings ss = new XmlReaderSettings();
            ss.IgnoreWhitespace = true;
            ss.IgnoreComments = false;
            //XmlException.XmlExceptionErrorCode.
            XmlReader xmlr = XmlReader.Create(rms, ss);
            while (!xmlr.EOF)
            {
                xmlr.Read();
                switch (xmlr.NodeType)
                {
                    case XmlNodeType.Element:
                        Debug.Print("element: " + xmlr.Name);
                        break;
                    case XmlNodeType.Text:
                        Debug.Print("text: " + xmlr.Value);
                        break;
                    case XmlNodeType.XmlDeclaration:
                        Debug.Print("decl: " + xmlr.Name + ", " + xmlr.Value);
                        break;
                    case XmlNodeType.Comment:
                        Debug.Print("comment " + xmlr.Value);
                        break;
                    case XmlNodeType.EndElement:
                        Debug.Print("end element");
                        break;
                    case XmlNodeType.Whitespace:
                        Debug.Print("white space");
                        break;
                    case XmlNodeType.None:
                        Debug.Print("none");
                        break;
                    default:
                        Debug.Print(xmlr.NodeType.ToString());
                        break;
                }
            }
            Debug.Print("The end");
        #endregion

Your device has a 112KB of memory. I suggest you check the amount of available memory after your have written the file.

Forcing GC before you start the read may help. Also look at the size of buffers allocated in the XML DLL.

// find available memory
int memoryAvail = Debug.GC(false);
Debug.Print("Avail memory before GC " + memoryAvail.ToString());

// find after GC
memoryAvail = Debug.GC(true);
Debug.Print("Avail memory after GC " + memoryAvail.ToString());

A disadvantage of legacy XML is its need of more resources. You may need to do some optimization here and there to get what you need.

You are working with one of the smallest devices so creative thinking maybe needed, or get something more beefy maybe.

I have boiled the code down to this only and the output is shown at the bottom (it looks like I should have plenty of memory)
In this case, I get the out of memory exception at:
reader.MoveToContent();

I have also tried various other XmlReader methods and they all have generated the same exception.

The two XML files I need to read are very small. I could do this with some basic parsing but was hoping to take the opportunity to learn a bit more about XML.

Also, I googled this a little and I am still not sure how to do this:
Also look at the size of buffers allocated in the XML DLL.

Thanks again. Any clues or more info. is much appreciated.

 Debug.Print("Avail memory before GC " + Debug.GC(false).ToString());
            Debug.Print("Avail memory after GC " + Debug.GC(true).ToString());
            string XmlData = @ "<?xml version=""1.0""?><note><body>This is the body.</body></note>";
            Debug.Print(XmlData.ToString());
            byte[] byteA = Encoding.UTF8.GetBytes(XmlData);

            MemoryStream byteAstream = new MemoryStream(byteA);
            XmlReader reader = XmlReader.Create(byteAstream);

            reader.MoveToContent();
            while (reader.Read()) 
            {
                // Do some work here on the data.
                Debug.Print(reader.Name);
                Thread.Sleep(1000);
            }

Output:
Avail memory before GC 48168
Avail memory after GC 48192

<?xml version="1.0"?>This is the body.

your before and after debug.print’s are together !

I’d suggest putting one of these debug.print’s between each statement through to the WHILE loop.

code is ok. different GG parameters. it’s shows that memory is not fragmented.

but it does show that 60k of the 112k available memory is gone before starting the code snippet. where did the memory go?

start a new project with only the posted code, and track the memory usage.

I still find it strange 50K is not enough for it to work! Maybe the legacy driver allocates large buffers internally.

Ok, this small example works now.

I started a new console application template(not the Gadgeteer template).
Cleaned up my code a little.
Added reference to System.Xml.Legacy
Removed all usings and libraries (i think i got them all) that were not required.

Starting with the Gadgeteer template seems problematic but I did not fully test that assumption

Thanks, Keith

using System;
using System.Threading;
using Microsoft.SPOT;

//usings added after start project created
using System.Xml;
using System.Text;
using System.IO;

namespace XmlReaderTest
{
    public partial class XmlReaderTest
    {
        static void Main()
        {
            Debug.Print("Avail memory before GC " + Debug.GC(false).ToString());
            Debug.Print("Avail memory after GC " + Debug.GC(true).ToString());

            string XmlData = @ "<?xml version=""1.0""?><note><body>This is the body.</body></note>";
            Debug.Print(XmlData.ToString());
            byte[] byteA = Encoding.UTF8.GetBytes(XmlData);

            MemoryStream byteAstream = new MemoryStream(byteA);
            XmlReader reader = XmlReader.Create(byteAstream);

            while (reader.Read())
            {
                Debug.Print(reader.Name);
                Thread.Sleep(100);
            }
            Thread.Sleep(Timeout.Infinite);
        }
    }
}

And the output is:

Avail memory before GC 71388
Avail memory after GC 71172

<?xml version="1.0"?>This is the body.

xml
note
body

body
note

I got memory exceptions when I did this:
I started a new project using the Gadgeteer template and used the code from the previous post.

The code works when I did this:
I Excluded this code from the project:

Program.gadgeteer
Program.gadgeteer.diagram
Program.generated.cs

Changed the entry point in program.cs to main.

You do not want to use a Gadgeteer project with a small memory device. It will eat up lots of memory, as you are seeing.

Use a regular Micro Framework project.

I have not found it possible to use XML with the Cerbiuno Bee. Reading an XML string of more than a few lines causes an out of memory condition.

If someone has worked with XML and this device, I would be interested in seeing it.

I am way to inexperienced to claim it is not possible, I could be doing something stupidly wrong.

I am writing my own parser. I don’t really need the power of XML. I was just interested in using it because it appeared to be the best choice programming wise.

Thanks for all the help. I have learned a ton more in the last month about these devices.

Keith

I’ve not looked into this yet, but is there JSON library available? I would imagine the data structures in JSON would require less run-time memory for similar data in XML.

Sounds like a bug to me; Panda II has less RAM and I’ve parsed XML with it.

You did not use legacy but native, right?

I’m not sure what you mean; I just used the normal XmlReader in the 4.1 framework on Panda II.

So I had to come back to this.
I started a new project and added the following code.
There is a for loop of 80 iterations to increase the memory usage.
The code runs without error.

Partial output at the end is:
Avail memory after GC 11772

Conclusion: Something in my original project was causing memory problems. I don’t know what specifically. So, I have not totally given up on XML yet with the Cerbuino Bee.

Keith

using System.IO;
using System.Xml;
using System.Ext.Xml;
using Microsoft.SPOT;

namespace MFConsoleApplication1
{
    public class Program
    {
        #region XML writer and reader
        static void Main()
        {
            // find available memory
            int memoryAvail = (int)Debug.GC(false);
            Debug.Print("Avail memory before GC " + memoryAvail.ToString());
            memoryAvail = (int)Debug.GC(true);
            Debug.Print("Avail memory after GC " + memoryAvail.ToString());


            MemoryStream ms = new MemoryStream();
            XmlWriter xmlwrite = XmlWriter.Create(ms);

            xmlwrite.WriteProcessingInstruction("xml",
                  "version=\"1.0\" encoding=\"utf-8\"");
            xmlwrite.WriteComment("This is just a comment");
            xmlwrite.WriteStartElement("NETMF_DataLogger");//root element
            xmlwrite.WriteStartElement("FileName");//child element
            xmlwrite.WriteString("Data");
            xmlwrite.WriteEndElement();
            xmlwrite.WriteStartElement("FileExt");
            xmlwrite.WriteString("txt");
            xmlwrite.WriteEndElement();
            for (int i = 0; i < 80; i++)
            {
                xmlwrite.WriteStartElement("SampleFeq");
                xmlwrite.WriteString("10");
                xmlwrite.WriteEndElement();
            }
            xmlwrite.WriteEndElement();//end the root element

            //xmlwrite.WriteString("<test>data</test>");

            xmlwrite.Flush();
            xmlwrite.Close();
            //////// display the XML data ///////////
            byte[] byteArray = ms.ToArray();
            char[] cc = System.Text.UTF8Encoding.UTF8.GetChars(byteArray);
            string str = new string(cc);
            Debug.Print(str);
            ms.Flush();
            ms.Close();

            ///////////read xml
            MemoryStream rms = new MemoryStream(byteArray);

            XmlReaderSettings ss = new XmlReaderSettings();
            ss.IgnoreWhitespace = true;
            ss.IgnoreComments = false;
            //XmlException.XmlExceptionErrorCode.
            XmlReader xmlr = XmlReader.Create(rms, ss);
            while (!xmlr.EOF)
            {
                xmlr.Read();
                memoryAvail = (int)Debug.GC(true);
                Debug.Print("Avail memory after GC " + memoryAvail.ToString());
                switch (xmlr.NodeType)
                {
                    case XmlNodeType.Element:
                        Debug.Print("element: " + xmlr.Name);
                        break;
                    case XmlNodeType.Text:
                        Debug.Print("text: " + xmlr.Value);
                        break;
                    case XmlNodeType.XmlDeclaration:
                        Debug.Print("decl: " + xmlr.Name + ", " + xmlr.Value);
                        break;
                    case XmlNodeType.Comment:
                        Debug.Print("comment " + xmlr.Value);
                        break;
                    case XmlNodeType.EndElement:
                        Debug.Print("end element");
                        break;
                    case XmlNodeType.Whitespace:
                        Debug.Print("white space");
                        break;
                    case XmlNodeType.None:
                        Debug.Print("none");
                        break;
                    default:
                        Debug.Print(xmlr.NodeType.ToString());
                        break;
                }
            }
            Debug.Print("The end");
            // find after GC

        #endregion
        }
    }
}