Какой правильный способ загрузить файл XML и переписать его как CSV? - PullRequest
1 голос
/ 05 мая 2010

Обновлено, чтобы быть ясным.

Шаг первый: у меня есть файл XML, который я хочу загрузить в DatGridView. (В основном работает благодаря Максу, но у меня все еще есть проблема с накопительным пакетом XML)

Шаг второй: запустить некоторый код на основе пользовательского ввода - (не является частью этого решения)

Шаг третий: экспорт DataGridView в файл CSV. (Решено Максом! Спасибо, мужик. Именно это я и пытался сделать в этой части.)

Использование VS 2008 C #

(Создан новый проект)

Пример из файла XML cars.xml

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <car>
    <year>2010</year>
    <make>Chevy</make>
    <model>Surburban</model>
    <color-e>Black</color-e>
    <color-i>Black</color-i>
    <features>
      <Engine>8 cylinder</Engine>
      <gas>Petrol</gas>
      <doors>5</doors>
      <miles>12312</miles>
    </features>
    </car>
  <car>
    <year>2001</year>
    <make>Ford</make>
    <model>Excursion</model>
    <color-e>Black</color-e>
    <color-i>Black</color-i>
    <features>
      <Engine>10 cylinder</Engine>
      <gas>Petrol</gas>
      <doors>5</doors>
      <miles>90312</miles>
    </features>
  </car>
  <car>
    <year>1999</year>
    <make>Chevy</make>
    <model>corvette</model>
    <color-e>Silver</color-e>
    <color-i>Black</color-i>
    <features>
      <Engine>8 cylinder</Engine>
      <gas>Petrol</gas>
      <doors>3</doors>
      <miles>44222</miles>
    </features>
  </car>
</root>

Это приложение winform. Он имеет две кнопки, одно текстовое поле и одно представление данных. Кнопка 1 должна загрузить данные XML в сетку данных. Затем кнопка два должна сохранить данные из таблицы данных в CSV-файл.

Вот код, который я до сих пор открывал и загружал xml в представление данных.

namespace carsXML
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
        var cars = XDocument.Load(@"C:\cars.xml");
        var query = from c in cars.Descendants("car")
                    select new
                    {
                        Year = (string)c.Element("year").Value,
                        Make = (string)c.Element("make").Value,
                        Model = (string)c.Element("model").Value,
                        // I needed to step directly into the sub element.
                        gas = (string)c.Element("features").Element("gas").Value,
                        doors = (string)c.Element("features").Element("doors").Value,
                        miles = (string)c.Element("features").Element("miles").Value


                    };

        dataGridView1.DataSource = query.ToList();

        }

        private void button2_Click(object sender, EventArgs e)
        {
          dataGridView1.ExportToCSV(@"C:\cars-griddump.csv"); 
         //Added Class Max showed me.  This works, I have only tested it on a small
         // XML file so far but it seems to work exactly as I wanted.
        }
    }
}

Получает элементы прямо под элементом автомобиля. Когда он попадает в элемент функции, приложение вылетает. (нулевой код и т. д.)

Итак, последняя часть этого, прежде чем я закончу с этим небольшим проектом, - это выяснение XML-накопления. Когда код читает элементы автомобиля, он получает все подчиненные элементы, которые находятся непосредственно под машиной. Сбой, когда он попадает к элементу, который имеет дополнительные подэлементы, и не добавляет их к представлению данных.

// Исправлена ​​проблема с накоплением. Это заняло у меня некоторое время! // Спасибо за помощь!

Ответы [ 3 ]

0 голосов
/ 05 мая 2010

Если вы не хотите использовать XSLT и XslCompiledTransform, посмотрите на LINQ to XML. Это просто и прямолинейно. Чтобы загрузить XML-файл, вы должны использовать XDocument.Load(path), а для извлечения элементов автомобиля вы должны использовать метод Decedents("car"). А затем просто зациклите элементы, записав их на выход.

var cars = XDocument.Load(path).Decedents("car");

LINQ to SQL

XSLT и XslCompiledTransform: найдите xslcompiledtransform в MSDN

Если вы используете VS2008, вы можете расширить DataGrid и создать вспомогательный класс для обработки всех ваших потребностей в экспорте.

  1. Добавьте этот [DataGridViewExtender] в свой проект, как показано ниже

    
    namespace System.Windows.Forms
    {
    using System;
    using System.Collections.Generic;
    using System.Windows.Forms;
    using System.IO;</p>
    
    <p>static class DataGridViewExtender
    {
        public static void ExportToCSV(this DataGridView grid, string path)
        {
            ExportToFile(grid, path, ",");
        }</p>
    
    <code>public static void ExportToFile(this DataGridView grid, string path, string separator)
    {
        if (grid.Columns.Count <= 0)
        { return; }
    
        using (var writer = new StreamWriter(path))
        {
            var values = new List<string>(grid.Columns.Count);
    
            foreach (DataGridViewColumn column in grid.Columns)
            {
                values.Add(column.Name);
            }
            writer.WriteLine(string.Join(separator, values.ToArray()));
            foreach (DataGridViewRow row in grid.Rows)
            {
                values.Clear();
                foreach (DataGridViewCell cell in row.Cells)
                {
                    values.Add(string.Format("{0}", cell.Value));
                }
                writer.WriteLine(string.Join(separator, values.ToArray()));
            }
            writer.Close();
        }
    }
    

    } }

  2. в button2_Click вызвать этот метод private void button2_Click(object sender, EventArgs e) { dataGridView1.ExportToCSV(@"C:\griddump.csv"); }

0 голосов
/ 05 мая 2010

В вашем вопросе не так много деталей, но лучшее, что я могу сделать, это предположить, что у вас есть XML-файл, содержащий информацию об автомобилях, например

<cars>
  <car>
    <make>Honda</model>
    <model>Odyssey</model>
    <year>2009</year>
  </car>
  <car>
    <make>Toyota</make>
    <model>Sienna</model>
    <year>2010</year>
  </car>
</cars>

А затем вы хотите написать CSV, который выглядит следующим образом:

make   model   year
Honda  Odyssey 2009
Toyota Sienna  2010

Поскольку вы пометили linq-to-xml, я предполагаю, что вы хотите использовать LINQ, хотя вы можете не знать, что делать дальше. Попробуйте использовать XDocument.Load для загрузки вашего XML-файла. Затем вы будете использовать Element () и Elements (), чтобы добраться до узлов в структуре XML. Например, если xml = XDocument.Load(filename), тогда xml.Element("cars") должен дать вам корневой узел. При этом вы можете использовать xml.Element("cars").Elements(), чтобы получить все элементы ... и так далее, и так далее.

0 голосов
/ 05 мая 2010

Один из способов - загрузить XML в набор данных, а затем сохранить набор данных в CSV. Это самый простой. Но это имеет некоторую зависимость от структуры дерева XML.

Обновление для отображения образца для сохранения DataTable в csv:

Мы можем вызвать этот метод для каждой таблицы данных в наборе данных

void SaveDTtoCSV(DataTable dt)
{
    // Save data to CSV file 
    StreamWriter writer = new StreamWriter(@"c:/dsoutput.csv");
    // First we will write the headers.
    int iColCount = dt.Columns.Count;
    for(int i = 0; i < iColCount; i++)
    {
        writer.Write(dt.Columns[i]);
        if (i < iColCount - 1)
        {
            writer.Write(",");
        }
    }
    writer.Write(writer.NewLine);
    // Now write all the rows.
    foreach (DataRow dr in dt.Rows)
    {
        for (int i = 0; i < iColCount; i++)
        {
            if (!Convert.IsDBNull(dr[i]))
            {
                writer.Write(dr[i].ToString());
            }
            if ( i < iColCount - 1)
            {
                writer.Write(",");
            }
        }
        writer.Write(writer.NewLine);
    }
    writer.Close();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...