Дата публикации статьи: 18.05.2006 10:08

Преобразование файлов с разделителями в XML

Автор: Tiberius OsBurn
[Оригинал статьи] [Обсудить в форуме]
Перевод с английского: Виталий Готовцов
WWW: http://www.vitgot.narod.ru

Скачать исходный код к статье

Эта статья демонстрирует преобразование файла с разделителями в DataSet или файл XML. Чтобы продемонстрировать это я создал файл с таб-разделителями для обслуживания номеров в Роуч-мотеле [Roach-Motel - дешевый мотель с минимум услуг (прим. переводчика)].

Зачем проводить преобразование?

Файлы с таб-разделителями и с запятыми-разделителями когда-то были стандартным способом представления данных вне реляционной базы данных. С появлением XML разработчики получили возможность предоставлять свои данные в гораздо более богатом и более описательном окружении без сложностей и расходов реляционных баз данных. Преобразование наследия файлов с разделителями в формат XML позволяет разработчикам получить преимущество многих новых технологий, которые возникают вокруг XML.

Для чего сначала нужно преобразовывать в DataSet?

Хорошей особенностью .Net-объекта DataSet является его способность сохранять внутренние данные как XML. В прошлом разработчики Microsoft были вынуждены использовать функцию Split() для анализа своих файлов с разделителями, а затем снова собирать строки воедино в файл XML-формата. При работе с большими файлами это стало особенно скверной практикой. .NET-объект DataSet делает за нас бóльшую часть работы, чисто и быстро. Мы будем использовать метод GetXml() объекта DataSet, чтобы преобразовать DataSet-представление файла с разделителями в XML-представление.

Приступим

Мы собираемся динамически создать DataSet с помощью объекта StreamReader, объекта DataTable и объекта DataRows.
Давайте взглянем на фрагмент XML, полученный из файла с таб-разделителями:

<Kitchen xmlns="The_Roach_Motel">
<Room_Service>
<Room_Number>290</Room_Number>
<Breakfast>Bagel</Breakfast>
<Lunch>Pizza</Lunch>
<Dinner>Salmon</Dinner>
</Room_Service>
</Kitchen>

Действительно приятным в соединении XML/DataSet является то, как происходит объединение ADO и XML. Я могу определить пространство имен моего XML-представления хотя бы с помощью свойства объекта DataSet:

oDS.DataSetName = "Kitchen"
oDS.Namespace = "The_Roach_Motel"

В верхнем фрагменте XML обратите внимание, что именем DataSet становится имя корневого элемента, а свойство Namespace замечательно переносится в XML.
Затем мы добавим таблицу 'Room_Service'. Я стараюсь не использовать пробелы в названиях таблиц DataSet и элементов XML.

oDS.Tables.Add("Room_Service")

Мы воспользуемся объектом StreamReader чтобы открыть файл с разделителями.

Dim oSR As New StreamReader(strFilePath)
'Go to the top of the file
oSR.BaseStream.Seek(0, SeekOrigin.Begin)

Большая часть файлов с разделителями содержат заголовок или группу описывающих имен, которые идентифицируют столбцы данных. Мы собираемся выделить первую строку нашего файла и использовать названия заголовков столбцов в качестве столбцов нашего DataSet. После того, как мы добавим новую таблицу в наш DataSet, мы добавим названия столбцов в нашу новую таблицу.
Обратите внимание, что мы применяем функцию Split к нашему объекту StreamReader чтобы разделить названия столбцов.

'Add in the Header Columns
For Each strFields In oSR.ReadLine().Split(strDelimiter)
    oDS.Tables(0).Columns.Add(strFields)
Next

После того, как мы добавили наши столбцы, мы можем начинать добавлять строки с данными. Нам будет необходимо подтвердить наш объект DataTable, установив связь с нашей таблицей в DataSet. После того, как это будет сделано, нам будет нужно создать объект DataRow. Объект DataRow содержит все данные строки и гарантирует, что данные размещены в правильных столбцах.

oTable = oDS.Tables(0)
While (oSR.Peek() > -1)
    oRows = oTable.NewRow()

Обратите внимание, что снова и снова мы обращаемся к объекту StreamReader. Нет необходимости инициализировать его или начинать с начала - мы уже получили столбцы и теперь просто перемещаем данные из файла с разделителями. Я добавил intCounter, чтобы обозначить номер столбца, так как мы не знаем его имени в текущий момент.

For Each strFields In oSR.ReadLine().Split(strDelimiter)
        oRows(intCounter) = strFields
        intCounter = intCounter + 1
    Next
    intCounter = 0

После того, как мы заполнили объект DataRows данными, мы будем готовы добавить эту строку в объект DataTable.

oTable.Rows.Add(oRows)
End While

Все, что осталось сделать, это конвертировать DataSet в XML с помощью функции GetXML() и вернуть XML в виде строки. Вы можете сохранить эту строку в XML-файл, используя функцию WriteXML().
Добавлю, что XML и ADO.NET даруют разработчикам свободу, преобразовывая наследие форматов данных в удобные, доступные запросам документы. Я надеюсь, что вы найдете эту статью полезной и она поможет вам.

Код в целом
Imports System
Imports System.IO
Imports System.Collections
Imports System.Data
Imports System.Text

Module modXML

    Sub Main()
        Dim strXML As String
        strXML = delimitedDataSet(vbTab, "c:/food.tab")
    End Sub

    Function delimitedDataSet(ByVal strDelimiter As String, _
        ByVal strFilePath As String) As String
        Dim oDS As New DataSet()
        Dim strFields As String
        Dim oTable As New DataTable()
        Dim oRows As DataRow
        Dim intCounter As Int32 = 0
        Dim oRow As DataRow()

        oDS.DataSetName = "Kitchen"
        oDS.Namespace = "The_Roach_Motel"
        oDS.Tables.Add("Room_Service")

        Dim oSR As New StreamReader(strFilePath)
        'Go to the top of the file
        oSR.BaseStream.Seek(0, SeekOrigin.Begin)
        'Add in the Header Columns
        For Each strFields In oSR.ReadLine().Split(strDelimiter)
            oDS.Tables(0).Columns.Add(strFields)
        Next

        'Now add in the Rows

        oTable = oDS.Tables(0)
        While (oSR.Peek() > -1)
            oRows = oTable.NewRow()
            For Each strFields In oSR.ReadLine().Split(strDelimiter)
                oRows(intCounter) = strFields
                intCounter = intCounter + 1
            Next
            intCounter = 0
            oTable.Rows.Add(oRows)
        End While
        Return oDS.GetXml()
        'oDS.WriteXml("c:/food.xml")
    End Function
Файл с таб-разделителями

Вот файл, который я создал, чтобы предоставить обслуживание номеров в этом знаменитом отеле.

Room_Number  Breakfast   Lunch      Dinner
290          Bagel       Pizza      Salmon
301          Orange      Pizza      Chicken ala King
349          Sweet Roll  Salad      Tofu and Vegetables
500          Omelet      Sausage    Veal
702          Eggs        Tuna fish  Cheese Sandwich
XML, полученный в результате

После того, как мы применили GetXml() к нашему DataSet, мы можем сохранить нашу строку как XML-файл.

<Kitchen xmlns="The_Roach_Motel">
<Room_Service>
<Room_Number>290</Room_Number>
<Breakfast>Bagel</Breakfast>
<Lunch>Pizza</Lunch>
<Dinner>Salmon</Dinner>
</Room_Service>
<Room_Service>
<Room_Number>301</Room_Number>
<Breakfast>Orange</Breakfast>
<Lunch>Pizza</Lunch>
<Dinner>Chicken ala King</Dinner>
</Room_Service>
<Room_Service>
<Room_Number>349</Room_Number>
<Breakfast>Sweet Roll</Breakfast>
<Lunch>Salad</Lunch>
<Dinner>Tofu and Vegetables</Dinner>
</Room_Service>
<Room_Service>
<Room_Number>500</Room_Number>
<Breakfast>Omelet</Breakfast>
<Lunch>Sausage</Lunch>
<Dinner>Veal</Dinner>
</Room_Service>
<Room_Service>
<Room_Number>702</Room_Number>
<Breakfast>Eggs</Breakfast>
<Lunch>Tuna fish</Lunch>
<Dinner>Cheese Sandwich</Dinner>
</Room_Service>
</Kitchen>