如何在具有自适应数组长度的XElement中创建XElements? [英] How to create XElements in XElement with adaptable array length?
问题描述
对于奇怪的措辞标题感到抱歉,但很难用一句简短的句子表达我的问题。
我正在编写一个导入类似CSV的功能数据转换成XML。我使用比MSDN示例更复杂的代码,但它基本上是相同的想法。
来自MSDN的示例:
Sorry about the weirdly phrased title, but it was hard to convey my issue in one short sentence.
I'm writing a feature to import CSV-like data into XML. And I'm using a bit more complex code than the MSDN example, but it's essentially the same idea.
Example from MSDN:
string[] source = File.ReadAllLines("customers.csv");
XElement customers = new XElement("Root",
from str in source
let fields = str.Split(',')
select new XElement("Customer",
new XAttribute("CustomerID", fields[0]),
new XElement("CompanyName", fields[1]),
new XElement("ContactName", fields[2]),
new XElement("ContactTitle", fields[3]),
new XElement("Phone", fields[4])
)
);
Console.WriteLine(customers);
问题是要导入的文件具有可变数量的列,并且他们在第一行中的列名,(我已经将第一行隔离为一个单独的数组),我想循环包含列名的数组并为每个列添加XElements。但是我无法获得任何标准的循环来给我我想要的结果。
我可能会错过一个明显的解决方案,但我的想法很新鲜
任何帮助都会非常感激
The problem is that the files to import have variable number of columns, and have their column names in first row, (I have isolated the first row as a separate array of course), and I would like to "loop through" the array containing column names and add XElements for each of them. However I can't get any standard "looping" to give me the result I want.
I might be missing an obvious solution, but I am fresh out of ideas
Any help would be much appreciated
推荐答案
你需要专门处理其中一个列吗?是XAttribute而不是XElement?如果没有,这可以简化......
Do you need to treat one of the columns specially to be the XAttribute instead of XElement? If not, this can be simplified...
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
namespace ConsoleApplication6
{
class Program
{
public static Dictionary<TKey, TValue> ZipIntoDictionary<TKey, TValue>(Dictionary<TKey, TValue> dict, IEnumerable<TKey> keys, IEnumerable<TValue> values)
{
dict = dict ?? new Dictionary<TKey, TValue>();
var enumKeys = keys.GetEnumerator();
var enumValues = values.GetEnumerator();
while (enumKeys.MoveNext() && enumValues.MoveNext())
{
dict.Add(enumKeys.Current, enumValues.Current);
}
return dict;
}
static void Main(string[] args)
{
string filePath = "customers.csv";
List<string> headers = null;
const string idKey = "CustomerID";
Dictionary<string, string> columns = null;
XElement customers = new XElement("Root");
using (StreamReader sr = new StreamReader(filePath))
{
string line;
// Read and process lines from the file until the end of the file is reached.
while ((line = sr.ReadLine()) != null)
{
if (string.IsNullOrWhiteSpace(line))
continue; // ignore blank lines (we've already dealt with null above)
string[] rawColumns = line.Split(',');
if (headers == null)
{
headers = rawColumns.ToList(); // capture the first non-blank line as headers
if (!headers.Contains(idKey)) // remove the idKey if there and report if it isn't
{
Console.WriteLine("Missing Identifier Key: " + idKey);
return;
}
continue; // no more processing of this line
}
columns = ZipIntoDictionary(columns, headers, rawColumns);
XElement thisCustomer = new XElement("Customer", new XAttribute(idKey, columns[idKey]));
foreach (var pair in columns)
{
if (pair.Key != idKey)
thisCustomer.Add(new XElement(pair.Key, pair.Value));
}
customers.Add(thisCustomer);
}
}
Console.WriteLine(customers);
}
}
}
大部分/全部硬编码字符串可以/应该作为参数传递。
这里有一点简化没有属性...
Most/all of the hard-coded strings could/should be passed as arguments.
Here it is a bit simplified for no attribute...
static void Main(string[] args)
{
string filePath = "customers.csv";
XElement customers = CsvToXml(filePath, "Root", "Customer");
Console.WriteLine(customers);
}
static XElement CsvToXml(string filePath, string rootName, string elementName)
{
string[] headers = null;
XElement root = new XElement(rootName);
using (StreamReader sr = new StreamReader(filePath))
{
string line;
// Read and process lines from the file until the end of the file is reached.
while ((line = sr.ReadLine()) != null)
{
if (string.IsNullOrWhiteSpace(line))
continue; // ignore blank lines (we've already dealt with null above)
string[] columns = line.Split(',');
if (headers == null)
{
headers = columns; // capture the first non-blank line as headers
continue; // no more processing of this line
}
XElement thisElement = new XElement(elementName);
for (int i = 0; i < headers.Length; i++)
{
string value = string.Empty;
if (i < columns.Length)
value = columns[i];
thisElement.Add(new XElement(headers[i], value));
}
root.Add(thisElement);
}
}
return root;
}
这篇关于如何在具有自适应数组长度的XElement中创建XElements?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!