另一个Element中的XML Element值在调试中停滞不前,没有返回

时间:2016-05-01 10:37:53

标签: c# .net xml linq linq-to-xml

我正在用C#编写XML解析器(LINQ to XML)。下面是XML结构的示例:

<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>

以下是提取值的C#代码段:

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;
});

这里的值都打印在textBoxLog TextBox中。当我运行程序时卡住了没有回报。另外,debuggin没有帮助,因为我无法读取值!在读取XML时似乎没有错误,好像我将读取值VALUES替换为它有效的ID。

例如,

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

由于VALUES节点在STRUCT节点内,我写了上面的代码。请说明问题出在哪里?

1 个答案:

答案 0 :(得分:0)

LINQ-to-XML对c# string length limit以外的XML节点文本的最大长度没有限制。如果在解析XML时超过该限制,则会得到OutOfMemoryException而不是挂起。

如果您的XML很大且包含许多元素,那么最可能的问题是,当您向其添加越来越多的文本时,TextBox需要花费很长时间才能进行更新。具体做法是:

  1. 您要为文件中的每个<ASB>设置一次TextBox.Text。这将导致文本框的许多更新和重新绘制,可能会使用消息淹没它,冻结GUI一段时间并导致明显的挂起。

    相反,您应该在StringBuilder中构建文字并仅将TextBox.Text设置为一次:

    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());
    

    请注意,如果您想要将文字附加到TextBoxRichTextBox,则应使用AppendText()。有关说明,请参阅herehere

  2. 如果您的XML文本非常庞大,TextBox似乎在更新和渲染时会冻结,尽管只将文本设置为一次,您可能需要重新考虑您的设计。

    一种可能是仅将前几百行文本添加到TextBox(或者至少比文本框中可见的行数更多),然后如果用户滚动到最后,使用AppendText()添加更多内容。

    要开始使用,您可以查看