Chuyển đổi giữa XML, XML Schema, Untyped và Typed DataSet

ADO.NET - Sử dụng các phương thức hỗ trợ sẵn của lớp DataSet, bạn có thể dễ dàng đọc một tập tin XML và chuyển thành DataSet.

Khi đã có một đối tượng DataSet trong ADO.NET bạn có thể ghi thành một tập tin XML Schema. Sau đây bạn sẽ thấy những công việc này sẽ đơn giản như thế nào nhờ .NET Framework và Visual Studio IDE.

1. Chuyển XML thành Untyped DataSet và ngược lại

Sẽ rõ ràng hơn nếu tôi đặt tiêu đề của phần này là “Nạp dữ liệu XML vào Untyped DataSet”. Tuy nhiên không chỉ đơn thuần là việc nạp dữ liệu, phương pháp này còn tự động phân tích và tạo ra các table và relationship giữa chúng trong DataSet.

Ví dụ, tôi có một file blog.xml với nội dung sau:

<?xml version='1.0'?>

<Blog>

    <Title>Just the beginning</Title>

    <Url>laptrinhtot.com</Url>

    <Author>

        <FirstName>Stanford</FirstName>

        <LastName>Day lap trinh</LastName>

    </Author>

</Blog>

Dựa vào nội dung của file trên, bạn có thể thiết kế được một mô hình database bao gồm relationship giữa các bảng không? Điều này tất nhiên có thể, nhưng điều này có thể được thực hiện một cách tự động bằng cách tạo ra một DataSet từ file .xml trên.

Phương pháp thực hiện rất đơn giản, bạn chỉ cần tạo một đối tượng DataSet rỗng và gọi phương thức ReadXML() trên DataSet đó. Tôi dùng overload đơn giản nhất của phương thức ReadXML() yêu cầu một tham số là đường dẫn đến file .xml:

DataSet ds = new DataSet();

ds.ReadXml(“C:\\blog.xml”, XmlReadMode.Auto);

Sau khi gọi phương thức ReadXML(), đối tượng DataSet sẽ chứa các table cùng với dữ liệu tương ứng của chúng, và ngoài ra, còn bao gồm cả relationship giữa các table. Đoạn chương trình hoàn chỉnh sau cung cấp một phương thức PrintData(DataSet) giúp in ra thông tin của DataSet cùng với dữ liệu và relationship để bạn kiểm tra trong cửa sổ Console:

using System;

using System.Data;

class Program

{

    static void Main()

    {

        DataSet ds = new DataSet();

        ds.ReadXml("C:\\blog.xml");

        PrintDataSet(ds);

        Console.Read();

    }

    static void PrintDataSet(DataSet ds)

    {

        foreach (DataTable table in ds.Tables)

        {

            Console.WriteLine("Table: " + table.TableName);

            Console.Write(" Columns: ");

            // column headers

            foreach (DataColumn col in table.Columns)

            {

                Console.Write("{0,-25}", col.ColumnName);

            }

            // rows

            foreach (DataRow row in table.Rows)

            {

                Console.Write("\n  -->   : ");

                foreach (var item in row.ItemArray)

                    Console.Write("{0,-25}", item);

                Console.WriteLine();

            }

            // separate line between tables

            Console.WriteLine("\n".PadRight(55, '='));

        }

        Console.WriteLine("Relationships:\n");

        foreach (var rel in ds.Relations)

        {

            Console.WriteLine(rel);

        }

    }

}

Output:

Table: Blog

 Columns: Title                    Url                      Blog_Id

  -->   : Just the beginning       laptrinhtot.com  0

======================================================

Table: Author

 Columns: FirstName                LastName                 Blog_Id

  -->   : Stanford                 Day lap trinh               0

======================================================

Relationships:

Blog_Author

Như bạn thấy DataSet của chúng ta bao gồm 2 table là Blog và Author,  cùng với một relationship (Blog_Author) liên kết giữa hai cột Blog_Id được tạo thêm giữa hai bảng.

Thay vì hiển thị theo cách này, sẽ rõ ràng hơn nếu bạn sử dụng một dự án ASP.NET hoặc Windows Fomr để hiển thị trên DataGrid.

Cùng với phương thức ReadXml(), DataSet còn cung cấp phương thức WriteXml(string fileName) giúp bạn chuyển dữ liệu của DataSet thành một tập tin XML.

Chuyển XML, Untyped DataSet thành XML Schema

Một mở rộng của ví dụ trên chỉ bằng cách thêm một dòng lệnh gọi phương thức WriteXmlSchema() của DataSet. Đúng vậy, công việc rất đơn giản, điều duy nhất bạn cần quan tâm là đặt file .xsd sẽ xuất ra là gì:

Ví dụ sau đọc dữ liệu từ file blog.xml và chuyển thành một fle XML schema (MyBlog.xsd) nhờ một đối tượng trung gian là DataSet (nên đặt tên file theo chuẩn đặt tên class của C# nếu bạn muốn chuyển file này một Typed DataSet).

static void Main()

{

    DataSet ds = new DataSet();

    ds.ReadXml("C:\\blog.xml");

    ds.WriteXmlSchema("C:\\myblog.xsd");

    Console.Read();

}

File MyBlog.xsd sau khi được tạo ra sẽ có nội dung:

<?xml version="1.0" standalone="yes"?>

<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">

  <xs:element name="Blog">

    <xs:complexType>

      <xs:sequence>

        <xs:element name="Title" type="xs:string" minOccurs="0" />

        <xs:element name="Url" type="xs:string" minOccurs="0" />

        <xs:element name="Author" minOccurs="0" maxOccurs="unbounded">

          <xs:complexType>

            <xs:sequence>

              <xs:element name="FirstName" type="xs:string" minOccurs="0" />

              <xs:element name="LastName" type="xs:string" minOccurs="0" />

            </xs:sequence>

          </xs:complexType>

        </xs:element>

      </xs:sequence>

    </xs:complexType>

  </xs:element>

  <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">

    <xs:complexType>

      <xs:choice minOccurs="0" maxOccurs="unbounded">

        <xs:element ref="Blog" />

      </xs:choice>

    </xs:complexType>

  </xs:element>

</xs:schema>

Nếu bạn muốn hiểu cơ bản về XML Schema, có thể đọc bài giới thiệu sau: XML Schema

Chuyển XML Schema thành Strongly Typed DataSet

Với file XML Schema được tạo ra trong phần trên, bạn hãy chú ý các thuộc tính id và name của các thẻ, chúng sẽ được dùng đặt tên cho các thành phần của Typed DataSet mà ta sắp tạo ra.

Để chuyển một file XML Schema thành một Typed DataSet trong Visual Studio, bạn chỉ cần nhấn chuột phải vào project, chọn Add>Existing Item… (Shift+Alt+A) và chọn đến file .xsd đó. Khi được thêm vào project, VS tự động tạo ra thêm các file tương ứng là MyBlog.Designer.cs, MyBlog.xsc và MyBlog.xss.

Double click vào file MyBlog.xsd trong Solution Explorer và bạn có thể thấy cửa sổ thiết kế Typed DataSet của file này bao gồm hai hai table như hình sau:


Mở file MyBlog.Designer.cs lên, bạn sẽ thấy được tên của Typed DataSet này là NewDataSet, chính là thuộc tính id của phần tử gốc xs:schema trong file XML Schema được tạo ra ở phần trên.

Một bất lợi của loại Typed DataSet này là bạn không thể cấu hình, tạo các query để lấy dữ liệu theo ý mình. Vì vậy việc nạp dữ liệu cho loại DataSet này phải được thực hiện bằng thuật toán. Tuy nhiên, bởi vì Typed DataSet được thừa kế từ lớp DataSet, bạn có thể dùng phương thức ReadXML() để nạp dữ liệu cho nó.

Trong giao diện designer của DataSet, bạn mở cửa sổ Properties và đổi tên của Typed DataSet trên từ NewDataSet thành MyBlog (property Name)


Sau đó bạn có thể chạy đoạn mã sau để tạo và nạp dữ liệu cho đối tượng MyBlog từ file .xml ban đầu. Bạn cũng có thể sử dụng phương thức PrintDataSet() để xem nội dung của đối tượng MyBlog này:

static void Main()

{

    MyBlog ds = new MyBlog();

    ds.ReadXml("C:\\blog.xml");

    // Console.WriteLine(ds.Blog.Rows.Count);

    PrintDataSet(ds);

    Console.Read();

}

Bạn có thể chắc chắn một điều là kết quả xuất sẽ tương tự như phần đầu tiên của bài viết này. Điểm khác duy nhất là vị trí của các cột, cụ thể là bạn sẽ thấy cột Blog_Id được đưa lên đầu.

Tags: