从 XML 创建泛型 table 的 LINQ 算法
LINQ algorithm to create generic table from XML
这是一段代码:
XNamespace z = "#SomeSchema";
var listCols = new HashSet<Col>();
var colNameList = new List<string>(..some values..);
var xElementList = doc.Descendants(z + "row");
return new HashSet<Row>(xElementList .Select(x=> new Row
{
Col= new List<Col>(listCols).Select(col =>
{
col.Value= (string)x.Attribute(colNameList.First(colName=> colName == col.Name));
return col;
}).ToList()
}));
错误的是,return 值包含一个行列表,但所有这些行都具有完全相同的值(对于 Col 值)。
例如,行[1].Col[1].Value == Row[2].Col[2].Value
而且这些值应该是完全不同的。我正在从 Xml 文件中获取这些值。当我调试 xElementList 时,值是不同的,但是当我尝试用它们创建行时,所有行都是相同的。
实际上,Rows有相同的Columns列表,也就是xElementList的最后一条记录。
我是不是做错了什么?
谢谢。
见下面的代码。我读了 xml 两遍。一次获取列名称并将列添加到 table。然后读取第2遍xml得到行数据
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
DataTable dt = new DataTable();
StreamReader sReader = new StreamReader(FILENAME, Encoding.GetEncoding(1252));
XmlReader reader = XmlReader.Create(sReader);
Dictionary<string, string> colDict = new Dictionary<string, string>();
while (!reader.EOF)
{
if (reader.Name != "FIELD")
{
reader.ReadToFollowing("FIELD");
}
if (!reader.EOF)
{
XElement field = (XElement)XElement.ReadFrom(reader);
string attrname = (string)field.Attribute("attrname");
string fieldtype = (string)field.Attribute("fieldtype");
switch (fieldtype)
{
case "string":
dt.Columns.Add(attrname, typeof(string));
break;
case "i4":
dt.Columns.Add(attrname, typeof(int));
break;
}
colDict.Add(attrname, fieldtype);
}
}
reader.Close();
sReader = new StreamReader(FILENAME, Encoding.GetEncoding(1252));
reader = XmlReader.Create(sReader);
while (!reader.EOF)
{
if (reader.Name != "ROW")
{
reader.ReadToFollowing("ROW");
}
if (!reader.EOF)
{
XElement row = (XElement)XElement.ReadFrom(reader);
DataRow newRow = dt.Rows.Add();
foreach (XAttribute attrib in row.Attributes())
{
string colName = attrib.Name.LocalName;
if (colDict.ContainsKey(colName))
{
switch (colDict[colName])
{
case "string":
newRow[colName] = (string)attrib;
break;
case "i4":
newRow[colName] = (int)attrib;
break;
}
}
}
}
}
}
}
}
这是一段代码:
XNamespace z = "#SomeSchema";
var listCols = new HashSet<Col>();
var colNameList = new List<string>(..some values..);
var xElementList = doc.Descendants(z + "row");
return new HashSet<Row>(xElementList .Select(x=> new Row
{
Col= new List<Col>(listCols).Select(col =>
{
col.Value= (string)x.Attribute(colNameList.First(colName=> colName == col.Name));
return col;
}).ToList()
}));
错误的是,return 值包含一个行列表,但所有这些行都具有完全相同的值(对于 Col 值)。
例如,行[1].Col[1].Value == Row[2].Col[2].Value
而且这些值应该是完全不同的。我正在从 Xml 文件中获取这些值。当我调试 xElementList 时,值是不同的,但是当我尝试用它们创建行时,所有行都是相同的。 实际上,Rows有相同的Columns列表,也就是xElementList的最后一条记录。
我是不是做错了什么?
谢谢。
见下面的代码。我读了 xml 两遍。一次获取列名称并将列添加到 table。然后读取第2遍xml得到行数据
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
DataTable dt = new DataTable();
StreamReader sReader = new StreamReader(FILENAME, Encoding.GetEncoding(1252));
XmlReader reader = XmlReader.Create(sReader);
Dictionary<string, string> colDict = new Dictionary<string, string>();
while (!reader.EOF)
{
if (reader.Name != "FIELD")
{
reader.ReadToFollowing("FIELD");
}
if (!reader.EOF)
{
XElement field = (XElement)XElement.ReadFrom(reader);
string attrname = (string)field.Attribute("attrname");
string fieldtype = (string)field.Attribute("fieldtype");
switch (fieldtype)
{
case "string":
dt.Columns.Add(attrname, typeof(string));
break;
case "i4":
dt.Columns.Add(attrname, typeof(int));
break;
}
colDict.Add(attrname, fieldtype);
}
}
reader.Close();
sReader = new StreamReader(FILENAME, Encoding.GetEncoding(1252));
reader = XmlReader.Create(sReader);
while (!reader.EOF)
{
if (reader.Name != "ROW")
{
reader.ReadToFollowing("ROW");
}
if (!reader.EOF)
{
XElement row = (XElement)XElement.ReadFrom(reader);
DataRow newRow = dt.Rows.Add();
foreach (XAttribute attrib in row.Attributes())
{
string colName = attrib.Name.LocalName;
if (colDict.ContainsKey(colName))
{
switch (colDict[colName])
{
case "string":
newRow[colName] = (string)attrib;
break;
case "i4":
newRow[colName] = (int)attrib;
break;
}
}
}
}
}
}
}
}