使用linq to XML将xml文件导入datagridview。数据无法正确显示

时间:2015-11-05 16:09:12

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

我的XML文件......

<?xml version="1.0" encoding="UTF-8"?>
<files>
        <file type="main">
<document>Report.pdf</document>
         <field name="Company">Northwind</field>
         <field name="Description">monthly report</field>
         <line>
               <field name="Description">Error</field>
               <field name="Type">4444</field>
         </line>
         <line>
               <field name="Description">Info</field>
               <field name="Type">4562</field>
         </line>
         <line>
               <field name="Description">Error</field>
               <field name="Type">2135</field>
         </line>
          <field name="Analyst">Bob</field>
          <field name="Manager">Steve</field>
          <field name="Dept">Finance</field>
          </file>
</files>

我的代码现在......

XElement xdoc = XElement.Load(@"C:\xmltest\input.xml");

                var lines = from item in xdoc.Descendants("line")

                            select new
                            {
                                Description = item.Value,
                                Type = item.Value

                            };

                dataGridView1.DataSource = lines.ToArray();

这是我得到的结果......

enter image description here

我想要的结果是......

enter image description here

我认为可能有效的准则......

 XElement xdoc = XElement.Load(@"C:\xmltest\input.xml");

                var lines = from item in xdoc.Descendants("line")

                            select new
                            {
                                Description = item.Attribute("field").Value,
                                Type = item.Value

                            };

                dataGridView1.DataSource = lines.ToArray();

我收到的错误是......

  

“对象引用未设置为对象的实例。”

3 个答案:

答案 0 :(得分:1)

您可以尝试按以下属性进行过滤:

XElement xdoc = XElement.Load(@"XMLFile1.xml");

var lines = from item in xdoc.Descendants("line")
            select new
            {
                Description = item.Elements("field").Where(e => (string)e.Attribute("name") == "Description").First().Value,
                Type = item.Elements("field").Where(e => (string)e.Attribute("name") == "Type").First().Value
            };

var array = lines.ToArray();

foreach (var item in array)
{
    Console.WriteLine($"{item.Description}\t{item.Type}");
}

它会产生以下结果:

Error   4444
Info    4562
Error   2135   

答案 1 :(得分:1)

DataSet怎么样?

sync()

答案 2 :(得分:1)

您的代码存在问题: -

item.Attribute("field").Value  //this line

只看到您的第一个查询,它返回该结果,因为item代表每个line节点,其中包含相应的field节点。比如说第一个item将是: -

<line>
  <field name="Description">Error</field>
  <field name="Type">4444</field>
</line>

依旧......

现在,在你说的第二个问题中,item.Attribute("field").Value它会抛出Null reference exception,因为每个item都不包含属性field(如上所示)而是element。所以你应该写item.Element("field")代替。但是,由于您希望根据属性值Descriptionname获取数据,因此仍无法获得预期的结果。您可以像这样编写查询: -

var lines = from item in xdoc.Descendants("line")
            let fields = item.Elements("field")
            select new
                {
                   Description = (string)fields
                       .FirstOrDefault(n => (string)n.Attribute("name") == "Description"),
                   Type = (string)fields
                       .FirstOrDefault(n => (string)n.Attribute("name") == "Type"),
                };

<强>解释

xdoc.Descendants("line")将获取所有行节点,如上所示,现在我们需要找到所有fields节点,因此我们将其存储在名为fields的变量中。最后,在投影时,我使用了FirstOrDefault方法来获取第一个匹配的name属性,其值为DescriptionType并获取其值。