使用 linq to XML 将 xml 文件导入 datagridview。数据显示不正确
Importing xml file to datagridview using linq to XML. data not displaying correctly
我的 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();
这些是我得到的结果...
我想要的结果是...
我认为代码可能有效...
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();
我收到的错误是...
"Object reference not set to an instance of an object."
您可以尝试像这样按属性过滤:
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
数据集怎么样?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
const string FILENAME = @"\temp\test.xml";
public Form1()
{
InitializeComponent();
DataSet ds = new DataSet();
ds.ReadXml(FILENAME);
dataGridView1.DataSource = ds.Tables[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")
来代替。但是,这仍然不会给你预期的结果,因为你想根据属性值 Description
和 name
获取数据。您可以这样编写查询:-
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
属性,其值为 Description
或 Type
并获取它的值。
我的 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();
这些是我得到的结果...
我想要的结果是...
我认为代码可能有效...
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();
我收到的错误是...
"Object reference not set to an instance of an object."
您可以尝试像这样按属性过滤:
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
数据集怎么样?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
const string FILENAME = @"\temp\test.xml";
public Form1()
{
InitializeComponent();
DataSet ds = new DataSet();
ds.ReadXml(FILENAME);
dataGridView1.DataSource = ds.Tables[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")
来代替。但是,这仍然不会给你预期的结果,因为你想根据属性值 Description
和 name
获取数据。您可以这样编写查询:-
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
属性,其值为 Description
或 Type
并获取它的值。