是否有更优雅的方式从XML文件中提取数据,该文件将其字段和数据完全存储在属性中?
我已经尝试了一个多月来从通过API获取的XML文件中提取数据,将其转换为DataTable,我使用C#,Visual Studio和.Net类来实现这一目标(特别是DOMDocument60,因为我发现的大多数例子都使用了它。)
使用任何这些示例都难以使用XML文件,因为它不是将数据存储在文本中而是存储在属性中。这是所有数据的返回方式:
<result>
<record>
<field name="donor_id" id="donor_id" value="33750"/>
<field name="first_name" id="first_name" value="Jacob"/>
<field name="last_name" id="last_name" value="LaBay"/>
</record>
<record>
<field name="donor_id" id="donor_id" value="33750"/>
<field name="first_name" id="first_name" value="Jacob"/>
<field name="last_name" id="last_name" value="LaBay"/>
</record>
</result>
正如您将看到的,字段名称位于&#34; name&#34;和&#34; id&#34;属性,值在&#34;值&#34;。
我尝试过的方法(下面)是首先通过迭代整个文件来获取列,查看&#34; id&#34;元素,并将它们作为列添加到DataTable,如果它们已经是列,则忽略它们,然后在添加列之后,解析具有&#34; value&#34;属性的所有元素,并添加它们作为该DataTable的行。问题是它效率低下(它需要在整个文件中继续查找可能的列,即使它在开头已经有了它),而且它也有错误 - 它经常崩溃。所以它很慢而且不稳定,而且我可以运行一些大的返回结果(我可以将API字符串输入到浏览器中,但看起来问题不在于XML,而是我的代码,正在解析它。)
以下是我提出的用于首先确定数据列的代码,然后是添加行的方法(该对象具有DataSet作为属性):
public void ProduceDataColumns()
{
DataTable table = new DataTable();
this.DataSet = new DataSet();
IXMLDOMNodeList objNodeList;
objNodeList = this.XMLDoc.selectNodes("//field");
foreach (IXMLDOMNode objNode in objNodeList)
{
if (objNode.nodeType == DOMNodeType.NODE_ELEMENT)
{
String str = objNode.attributes.getNamedItem("name").nodeValue;
String str2 = str.Replace("_", "__");
if (!table.Columns.Contains(str2))
{
table.Columns.Add(str2);
}
}
}
this.DataSet.Tables.Add(table);
}
public void ProduceDataRows()
{
IXMLDOMNodeList objNodeList;
objNodeList = this.XMLDoc.selectNodes("//record");
int i;
IXMLDOMNode objNode = objNodeList[0];
for (i = 0; i < objNodeList.length; i++)
{
object[] array = new object[objNode.childNodes.length];
//DataRow dataRow = new DataRow();
int j;
for (j = 0; j < objNode.childNodes.length; j++)
{
array[j] = objNodeList[i].childNodes[j].attributes.getNamedItem("value").nodeValue;
}
this.DataSet.Tables[0].Rows.Add(array);
}
}
如果有人能帮我提出更好的解决方法,我会永远感激不尽。我仍然对解析可用的XML文档的无数方法感到困惑。如果您需要更多信息,请与我们联系。
更新:我尝试了jdweng的方法,但它导致了一种对角线的数据分布。我觉得这个foreach已经缺失了,但我已经搞了一段时间并且无法使用它(我仍然对Linq感到困惑)。
以下是WPF DataGrid中DataSet的图像:
答案 0 :(得分:1)
这是使用已发布的xml开始的代码。我认为当你发布更好的xml输入样本时,他的代码需要修改。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Data;
namespace ConsoleApplication65
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
string[] uniqueIds = doc.Descendants("field").Select(x => (string)x.Attribute("id")).Distinct().ToArray();
DataTable dt = new DataTable();
foreach (string col in uniqueIds)
{
dt.Columns.Add(col, typeof(string));
}
foreach (XElement record in doc.Descendants("record"))
{
DataRow row = dt.Rows.Add();
foreach (XElement field in record.Elements("field"))
{
row[(string)field.Attribute("id")] = (string)field.Attribute("value");
}
}
}
}
}