如何在具有自适应数组长度的XElement中创建XElements? [英] How to create XElements in XElement with adaptable array length?

查看:87
本文介绍了如何在具有自适应数组长度的XElement中创建XElements?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于奇怪的措辞标题感到抱歉,但很难用一句简短的句子表达我的问题。



我正在编写一个导入类似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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆