Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XElement.ToString() causes System.OutOfMemoryException

I have an XElement object that contains about 120MB of data. The XML consists of approx 6000 elements of about 20kb each.

I am trying to call XElement.ToString() as I need to return the OuterXml in a webservice.

I am getting a System.OutOfMemoryException.

System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
   at System.String.GetStringForStringBuilder(String value, Int32 startIndex, Int32 length, Int32 capacity)
   at System.Text.StringBuilder.GetNewString(String currentString, Int32 requiredLength)
   at System.Text.StringBuilder.Append(Char[] value, Int32 startIndex, Int32 charCount)
   at System.IO.StringWriter.Write(Char[] buffer, Int32 index, Int32 count)
   at System.Xml.XmlEncodedRawTextWriter.FlushBuffer()
   at System.Xml.XmlEncodedRawTextWriter.WriteAttributeTextBlock(Char* pSrc, Char* pSrcEnd)
   at System.Xml.XmlEncodedRawTextWriter.WriteString(String text)
   at System.Xml.XmlEncodedRawTextWriterIndent.WriteString(String text)
   at System.Xml.XmlWellFormedWriter.WriteString(String text)
   at System.Xml.XmlWriter.WriteAttributeString(String prefix, String localName, String ns, String value)
   at System.Xml.Linq.ElementWriter.WriteStartElement(XElement e)
   at System.Xml.Linq.ElementWriter.WriteElement(XElement e)
   at System.Xml.Linq.XElement.WriteTo(XmlWriter writer)
   at System.Xml.Linq.XNode.GetXmlString(SaveOptions o)
   at System.Xml.Linq.XNode.ToString()

I have the same data in an XmlDocument and can call XmlDocument.OuterXml without a problem. I can also call XElement.Save() to save the XML to a file without a problem.

Can anyone suggest an alternative to XElement.ToString() that would be less memory intensive? Or alternatively some parameters I can set that would allow for a larger memory space?

like image 490
Robin Day Avatar asked Aug 21 '26 12:08

Robin Day


1 Answers

It sounds like you're writing way too much data there; generally raw XmlWriter might be the best option for this volume. However, if you can Save() successfully you could perhaps try:

    string xml;
    using(var sw = new StringWriter()) {
        el.Save(sw);
        xml = sw.ToString();
    }

or maybe:

    string xml;
    using (var ms = new MemoryStream()) { 
        using(var tw = new StreamWriter(ms, Encoding.UTF8))
        {
            el.Save(tw);            
        }
        xml = Encoding.UTF8.GetString(ms.GetBuffer(), 0, (int)ms.Length);
    }

But either (or both) of these might still explode in a shower of sparks. You might also want to investigate XStreamingElement which is designed for this type of scenario... but still, that is a lot of xml - especially for a web-service. Would you be open to suggestions of alternative (much denser) serializiation formats?

like image 90
Marc Gravell Avatar answered Aug 24 '26 03:08

Marc Gravell