0

I am writing a XML parser (LINQ to XML) in C#. Below is an example of the XML structure:

<ASB CATEGORY="TUBE">
  <VERSION>700114d2fefesdse34be9cab26a</VERSION>
  <ID>106107</ID>
  <STRUCT>
    <VALUES>9.19 48.491, 9.372 48.56555, 9.4222 48.57472, 9.62361111 48.64833333, 9.74722222 48.680833, 9.74622531 48.665604, 9.744127737 48.65018037, 9.7410232 48.63496203183, 9.7369276269873 48.61984372, 9.73361111 48.60972222, 9.6255556 48.5625, 9.1538889 48.4489, 9.19111 48.491111111</VALUES>
  </STRUCT>
</ASB>

Here is the C# code snippet to extract values:

string strAppPath = Path.GetDirectoryName(Path.GetDirectoryName(System.IO.Directory.GetCurrentDirectory()));
XDocument xdoc = XDocument.Load(strAppPath + "\\database\\test.xml");
xdoc.Descendants("ASB").Select(p => new {
    CATEGORY = p.Attribute("CATEGORY").Value,
    VALUES = p.Element("STRUCT").Element("VALUES").Value
}).ToList().ForEach(p => {
    textBoxLog.Text += "CATEGORY: " + p.CATEGORY + System.Environment.NewLine + p.VALUES + System.Environment.NewLine + System.Environment.NewLine;
});

Here the values are all printed in the textBoxLog TextBox. When I run the program gets stuck with no return. Also debuggin is no help as I can't read the values! There seems to be no bug in reading XML as if I replace reading values VALUES with ID it works.

For example,

ID = p.Element("ID").Value // Works
VALUES = p.Element("STRUCT").Element("VALUES").Value // Doesn"t work

Since the VALUES node is inside the STRUCT node, I though of writing the above code. Please suggest where is the problem?

dDebug
  • 57
  • 1
  • 1
  • 8
  • 1
    You need to create a [mcve]. [This fiddle](https://dotnetfiddle.net/9PgSQz) has your code as a console app and it works fine. – Charles Mager May 01 '16 at 15:39
  • Thanks Charles for the suggestion! I can see the code works! The real problem is I have the XML and its huge, there are several ASB elements and in some cases the number of data points inside VALUES are really huge (about 600 data points). The code didn't work on the XML file but this small block works! Could be be a limit in Linq for maximum length of a node? If so how to handle that? – dDebug May 02 '16 at 13:55
  • Linq has no limit for maximum length of a text node other than the [c# string length limit](https://stackoverflow.com/questions/140468). 1) How big is this "huge" XML file? 2) Does it really make sense to display all these value in a `TextBox`? – dbc May 02 '16 at 15:35
  • Just to confirm, you are using [tag:winforms] for the `TextBox`, right? – dbc May 02 '16 at 20:20
  • Yes I'm using winforms and its not necessary to display in a textbox, I'm doing this be sure the parsing works correctly. I need to export some value to a text file – dDebug May 03 '16 at 09:49
  • The XML file is 3MB approx. – dDebug May 03 '16 at 09:50
  • If you're only using winforms for debugging, I recommend you output your intermediate results to some log file at, say, `Path.GetTempPath()` instead. Or, use `Debug.WriteLine()`. As @CharlesMager said your XML parsing looks fine so in my opinion the problem is likely something with winforms where the message loop is either not being serviced, or is swamped. – dbc May 03 '16 at 16:48

1 Answers1

0

LINQ-to-XML has no limit for maximum length of the text of an XML node other than the c# string length limit. If you exceed that limit while parsing XML you will get an OutOfMemoryException rather than a hang.

If your XML is large with many elements, then the most likely problem is that your TextBox is taking a very long time to update as you add more and more text to it. Specifically:

  1. You are setting the TextBox.Text once for every <ASB> in the file. This will cause many updates and repaints of the text box, potentially swamping it with messages, freezing the GUI for an extended period and causing an apparent hang.

    Instead, you should build your text up in a StringBuilder and set the TextBox.Text only once:

    var sb = new StringBuilder();
    foreach (var p in xdoc.Descendants("ASB"))
    {
        var CATEGORY = (string)p.Attribute("CATEGORY");
        var VALUES = (string)p.Element("STRUCT").Element("VALUES");
        sb.Append("CATEGORY: ").Append(CATEGORY).AppendLine().AppendFormat(VALUES).AppendLine().AppendLine();
    }
    
    textBoxLog.Text = sb.ToString();
    
    // Or if you want to add to pre-existing text, do
    // textBoxLog.AppendText(sb.ToString());
    

    Note that if you ever want to append text to a TextBox or RichTextBox, you should use AppendText(). For an explanation, see here or here.

  2. If your XML text is so enormous that the TextBox seems to freeze while updating and rendering itself despite setting the text just the once, you might need to re-think your design.

    One possible would be to add only the first few hundred lines of text to the TextBox (or at least, more than the visible number of lines in the text box), then if the user scrolls to the end, add more using AppendText().

    To get started, you might check out

dbc
  • 104,963
  • 20
  • 228
  • 340
  • This is the true reason, now its working!! TextBox can't update in this huge loop.. Thanks for the suggestion! – dDebug May 03 '16 at 17:10