Chủ nhật, ngày 4 tháng 12 năm 2016

LINQ cơ bản– Tổng quan về kiến trúc LINQ to XML

Ngày đăng: 14/3/2012, 8:39:53PM | Lượt xem: 4,380
Hot!

XML là một ngôn ngữ được ứng dụng rất nhiều trong lập trình, xử lý dữ liệu cũng như truyền tải thông tin. Trước đây việc thao tác và tạo ra các tài liệu XML thông qua DOM XML API trong .Net rất dài dòng và rắc rối. Vì thế để khắc phục điều này, Microsoft đã cho ra đời LINQ cùng với LINQ to XML API.

XML là một ngôn ngữ được ứng dụng rất nhiều trong lập trình, xử lý dữ liệu cũng như truyền tải thông tin. Trước đây việc thao tác và tạo ra các tài liệu XML thông qua DOM XML API trong .Net rất dài dòng và rắc rối. Vì thế để khắc phục điều này, Microsoft đã cho ra đời LINQ cùng với LINQ to XML API.

Từ DOM XML API đến LINQ to XML API

Ví dụ để tạo một tài liệu XML đơn giản sau.

Blog.xml:

<Blog>
  <Title>YinYang's Programming Blog</Title>
  <Author>
    <FirstName>Yin</FirstName>
    <LastName>Yang</LastName>
  </Author>
  <Categories>
    <Category>LINQ</Category>
    <Category>WPF</Category>
    <Category>ADO.NET</Category>
  </Categories>
</Blog>

Sử dụng cách cũ với DOM XML API (namespace System.Xml):

XmlDocument doc = new XmlDocument();

XmlElement blog = doc.CreateElement("Blog");

XmlElement title = doc.CreateElement("Title");
title.InnerText = "YinYang's Programming Blog";

XmlElement author = doc.CreateElement("Author");

XmlElement firstName = doc.CreateElement("FirstName");
firstName.InnerText = "Yin";
XmlElement lastName = doc.CreateElement("LastName");
lastName.InnerText = "Yang";

XmlElement categories = doc.CreateElement("Categories");
XmlElement category1 = doc.CreateElement("Category");
category1.InnerText = "LINQ";
XmlElement category2 = doc.CreateElement("Category");
category2.InnerText = "WPF";
XmlElement category3 = doc.CreateElement("Category");
category3.InnerText = "ADO.NET";

categories.AppendChild(category1);
categories.AppendChild(category2);
categories.AppendChild(category3);

author.AppendChild(firstName);
author.AppendChild(lastName);

blog.AppendChild(title);
blog.AppendChild(author);
blog.AppendChild(categories);

doc.AppendChild(blog);

// doc.Save("C:\\Blog.xml");

Đoạn mã trên mặc dù rất dễ hiểu nhưng cú pháp lại quá dài dòng. Việc tạo ra một cấu trúc XML theo cách trên chỉ tập trung vào hai phương thức: CreateElement() để tạo một phần tử mới và AppendChild() để thêm phần tử con vào phần tử hiện tại. Đây quả thực là một thứ dễ gây chán nản nếu như bạn phải thường xuyên làm việc với chúng.

Bây giờ ta thử xem cách mới theo LINQ to XML (namespace System.Xml.Linq):

XElement root =
new XElement("Blog",
    new XElement("Title", "YinYang's Programming Blog"),
    new XElement("Author",
        new XElement("FirstName", "Yin"),
        new XElement("LastName", "Yang")),
    new XElement("Categories",
        new XElement("Category", "LINQ"),
        new XElement("Category", "WPF"),
        new XElement("Category", "ADO.NET")
        )
);

Rất đơn giản và dễ hiểu, chỉ cần duy nhất một lớp XElement để tạo ra một tài liệu XML như trên. Điểm chính của cách làm này là sử dụng từ khóa params. Cho phép truyền một số lượng tham số không xác định vào phương thức. Một overload của constructor lớp XElement được sử dụng nhiều nhất là:

public XElement(XName name, params object[] content);

Theo overload này, một phần tử được tạo ra dựa hai yếu tố: tên của phần tử và các phần tử con của nó.

Tất cả các phần tử thuộc mảng content trong tham số trên đều trở thành phần tử con của đối tượng XElement được định nghĩa.

Và như bạn thấy với cú pháp này, mã nguồn được rút gọn rất nhiều so với cách cũ. Tuy nhiên do các tham số được lồng nhau và phân cấp trên một dòng lệnh nên một rắc rối mà ta gặp phải là khó xác định được cấu trúc của tài liệu XML được tạo ra.

Vì lý do trên, bạn nên hạn chế lồng quá nhiều phần tử và phân cấp quá nhiều khi tạo một đối tượng XElement. Chia ra khởi tạo nhiều XElement sau đó hợp lại là cách tốt để làm đoạn mã dễ hiểu hơn. Một lời khuyên đơn giản nữa là khi viết code, bạn hãy giữ việc thụt lề theo cấp độ của phần tử trong tài liệu XML như trong đoạn mã ví dụ trên, như vậy nội dung và cấu trúc của tài liệu XML gần như hiện lên trước mắt bạn.

Cây phân cấp lớp của LINQ to XML API

Sau khi lược bỏ một vài lớp mà tôi sẽ chưa bàn tới, ta có cây phân cấp lớp của LINQ to XML API, tất cả các lớp này đểu nằm trong namespace System.Xml.Linq. Tuy nhiên bạn cũng cần add reference đến namespace System.Xml do các lớp thừa kế một vài interface từ namespace này như IXmlLineInfo, IXmlSerializable:

Công dụng của mỗi lớp trên có thể được nhận biết ngay từ tên gọi của chúng, tuy nhiên để đảm bảo mọi thứ rõ ràng, tôi đã tạo một bảng liệt kê các lớp này cùng với mô tả ngắn gọn của chúng. Nếu muốn xem chi tiết hơn, bạn có thể tham khảo trên MSDN, xem metadata trong Visual Studio hoặc chi tiết hơn là dùng một công cụ .Net Reflector (ví dụ ILSpy).

Class Description
XName Represents a name of an XML element or attribute
XNamespace Represents an XML namespace. This class cannot be inherited
XObject Represents a node or an attribute in an XML tree
XAttribute Represents an XML attribute
XNode Represents the abstract concept of a node (element, comment, document type, processing instruction, or text node) in the XML tree
XText Represents a text node
XComment Represents an XML comment
XContainer Represents a node that can contain other nodes
XElement Represents an XML element
XDocument Represents an XML document

Sau khi đã có cái nhìn tổng quan về mô hình lớp của API này, ta sẽ đi sâu hơn vào xem xét một vài lớp chính mà ta sẽ không thể bỏ lỡ nếu như muốn làm thành thạo được LINQ to XML.

XNamespace

Đại diện cho một namespace trong tài liệu XML. Bạn có thể tạo thể hiện của lớp này từ một đối tượng string có dạng URI.

XNamespace ns=”http://yinyangit.wordpress.com/namespace

Để gán namespace cho một phần tử, thông thường ta sẽ tạo một đối tượng XNamespace và dùng toán tử cộng để tạo ra một tên đầy đủ cho phần tử:

XNamespace ns=”http://yinyangit.wordpress.com/namespace”
XElement x= new XElement(ns+”FirstElement”);

Để hiểu thêm về XML Namespace bạn có thể xem bài hướng dẫn tại trang sau:

http://www.w3schools.com/XML/xml_namespaces.asp

XName

Mỗi phần tử XML được tạo ra đều phải có tên, và tên này được đại diện bằng một đối tượng XName. Về cơ bản, XName là một định danh bao gồm tên cục bộ và tên namespace của phần tử (bao gồm XNamespace). Giống như XNamespace, XName có thể tự động được tạo ra từ một đối tượng string bằng cách overload operator:

public static implicit operator XName(string expandedName);

Một đối tượng XName sẽ được tạo ra trong mỗi dòng lệnh sau:

XName name = “Test”;

XElement root = new XElement(“Test”);

Ngoài ra bạn có thể tạo một XName bao gồm tên cục bộ và namespace bằng cách đặt tên namespace trong cặp {} và theo sau đó là tên cục bộ:

XName name=”{http://yinyangit.wordpress.com}Test”;

Khi đó property LocalName sẽ là “Test” và Namespace sẽ là http://yinyangit.wordpress.com.

XObject

Được thừa kế từ System.Object  và IXmlLineInfo (System.Xml), XObject là một lớp abstract nằm ở đỉnh của cây phân cấp mà tôi minh họa ở trên. Lớp này cung cấp các property cần thiết giúp ta truy xuất được những phần tử liên quan và một số thông tin cần thiết của phần tử trong tài liệu XML.

-          Document: đối tượng XDocument chứa toàn bộ cấu trúc và nội dung của tài liệu XML.

-          NoteType: lưu giá trị kiểu enum XmlNodeType xác định kiểu của phần tử.

-          Parent: tham chiếu đến phần tử cha có kiểu XElement.

Ngoài ra lớp này chứa hai event là ChangedChanging được kích hoạt mỗi khi phần tử bị thay đổi. Hai event này có kiểu EventHandler<XObjectChangeEventArgs>. Lớp XObjectChangeEventArgs chứa property có kiểu XObjectChange, đây là một enum chỉ ra kiểu thay đổi tác động đến phần tử, bao gồm 4 giá trị: Add, Remove, Name (đối tên), Value (đổi giá trị).

using System;
using System.Xml.Linq;

class LinqToXmlEx
{
    static void Main(string[] args)
    {

        XElement root = new XElement("Root");
        XElement lchild = new XElement("LChild","Foo");
        XElement rchild = new XElement("RChild","Bar");

        root.Changing += (sender, e) =>
        {
            Console.WriteLine("Changing type: " + e.ObjectChange);
        };

        root.Add(lchild);
        root.Add(rchild);
        lchild.Name = "LeftChild";
        rchild.Add("rel");
        lchild.Remove();

        Console.WriteLine("----------");
        Console.WriteLine(root);

        Console.Read();
    }
}

Output:

Changing type: Add
Changing type: Add
Changing type: Name
Changing type: Value
Changing type: Remove

———-

<Root>
<RChild>Barrel</RChild>
</Root>

Thêm vào đó, XObject cho phép bạn thêm các annotation để bổ sung thông tin cho đối tượng. Các thông tin annotation chỉ là tạm thời, không phải là một phần của tài liệu XML và sẽ không được lưu xuống file. Các phương thức làm việc với annotation trong XObject:

Name Description
AddAnnotation Adds an object to the annotation list of this XObject.
Annotation(Type) Gets the first annotation object of the specified type from this XObject.
Annotation<T>() Get the first annotation object of the specified type from this XObject.
Annotations(Type) Gets a collection of annotations of the specified type for this XObject.
Annotations<T>() Gets a collection of annotations of the specified type for this XObject.
RemoveAnnotations(Type) Removes the annotations of the specified type from this XObject.
RemoveAnnotations<T>() Removes the annotations of the specified type from this XObject.

XAttribute

Một phần tử XML có thể chứa nhiều attribute, mỗi attribute này được đại diện bởi một đối tượng XAttribute. Bạn có thể truy xuất đến các attribute trước và sau bằng cách dùng hai property PreviousAttribute và NextAttribute. Trong trường hợp attribute là một khai báo namespace, property IsNamespaceDeclaration sẽ trả về true.

XNode

Đại diện cho các phần tử (element, comment, document type, processing instruction, text node). XNode cho phép bạn truy xuất đến các phần tử trước và sau với PreviousNode và NextNode.

Một đặc điểm quan trọng của XNode là cung cấp các phương thức dùng để thêm/xóa/sửa các phần tử trong tài liệu XML. Các phần tử được thêm vào sẽ có cùng level với nhau và có cùng phần tử cha.

Name Description
AddAfterSelf(Object) Adds the specified content immediately after this node.
AddAfterSelf(Object[]) Adds the specified content immediately after this node.
AddBeforeSelf(Object) Adds the specified content immediately before this node.
AddBeforeSelf(Object[]) Adds the specified content immediately before this node.
Remove Removes this node from its parent.
ReplaceWith(Object) Replaces this node with the specified content.
ReplaceWith(Object[]) Replaces this node with the specified content.

Ngoài ra còn có các phương thức để duyệt các phần tử trong tài liệu XML như Ancestors() dùng để lấy về một collection các phần tử có level cao hơn (tổ tiên):

Name Description
Ancestors() Returns a collection of the ancestor elements of this node.
Ancestors(XName) Returns a filtered collection of the ancestor elements of this node. Only elements that have a matching XName are included in the collection.
ElementsAfterSelf() Returns a collection of the sibling elements after this node, in document order.
ElementsAfterSelf(XName) Returns a filtered collection of the sibling elements after this node, in document order. Only elements that have a matching XName are included in the collection.
ElementsBeforeSelf() Returns a collection of the sibling elements before this node, in document order.
ElementsBeforeSelf(XName) Returns a filtered collection of the sibling elements before this node, in document order. Only elements that have a matching XName are included in the collection.
IsAfter Determines if the current node appears after a specified node in terms of document order.
IsBefore Determines if the current node appears before a specified node in terms of document order.
NodesAfterSelf Returns a collection of the sibling nodes after this node, in document order.
NodesBeforeSelf Returns a collection of the sibling nodes before this node, in document order.

Lớp này còn chứa các phương thức để đọc, ghi nội dung XML. Vấn đề này ta sẽ đề cập tới chi tiết hơn trong một bài viết khác.

XText và XComment

Các phần tử này chỉ chứa property Value lưu giá trị của văn bản, chú thích. Một dạng wrapper của string.

XContainer

Dùng để chứa các phần tử khác. Lớp này cung cấp hai property là FirstNode và LastNode cho phép truy xuất đến phần tử đầu và cuối. Ngoài ra bổ sung thêm cho lớp XNode các phương thức để thêm phần tử con vào.

Các phương thức mà bạn cần quan tâm của lớp này:

Name Description
Add(Object) Adds the specified content as children of this XContainer.
Add(Object[]) Adds the specified content as children of this XContainer.
AddFirst(Object) Adds the specified content as the first children of this document or element.
AddFirst(Object[]) Adds the specified content as the first children of this document or element.
DescendantNodes Returns a collection of the descendant nodes for this document or element, in document order.
Descendants() Returns a collection of the descendant elements for this document or element, in document order.
Descendants(XName) Returns a filtered collection of the descendant elements for this document or element, in document order. Only elements that have a matching XName are included in the collection.
Element Gets the first (in document order) child element with the specifiedXName.
Elements() Returns a collection of the child elements of this element or document, in document order.
Elements(XName) Returns a filtered collection of the child elements of this element or document, in document order. Only elements that have a matchingXName are included in the collection.
Nodes Returns a collection of the child nodes of this element or document, in document order.
RemoveNodes Removes the child nodes from this document or element.
ReplaceNodes(Object) Replaces the children nodes of this document or element with the specified content.
ReplaceNodes(Object[]) Replaces the children nodes of this document or element with the specified content.

XElement

Đại diện cho một phần tử, lớp này tương tự như XNode và XContainer, bổ sung thêm một số thuộc tính và phương thức ví dụ như Attributes() để lấy về các attribute của phần tử. Đặc trưng chính của lớp này là các phương thức Parse, Load, Save nội dung của văn bản hoặc tập tin thành một phần tử.

Ví dụ ta sử dụng Parse() để tạo một phần tử XML từ một đoạn văn bản. Hai đối tượng x1 và x2 sau sẽ tạo ra một phần tử giống nhau:

XElement x1=XElement.Parse("<Blog title=\"Let me know what you think\"><Name>Yin Yang</Name></Blog>");

XElement x2=new XElement("Blog",
new XAttribute("title","Let me know what you think"),
new XElement("Name","Yin Yang"));

Tài liệu XML được tạo ra từ x1 và x2 trên sẽ có cùng nội dung như sau:

<Blog title="Let me know what you think">
  <Name>Yin Yang</Name>
</Blog>

XDocument

XDocument là lớp đại diện cho toàn bộ một tài liệu XML. Sau đây là một ví dụ tương đối hoàn chỉnh từ MSDN cho những gì bạn mới học:

using System;
using System.Linq;
using System.Xml.Linq;

public class Linq2XmlExample {
    public static void Main() {
        XDocument srcTree = new XDocument(
            new XComment("This is a comment"),
            new XElement("Root",
                         new XElement("Child1", "data1"),
                         new XElement("Child2", "data2"),
                         new XElement("Child3", "data3"),
                         new XElement("Child2", "data4"),
                         new XElement("Info5", "info5"),
                         new XElement("Info6", "info6"),
                         new XElement("Info7", "info7"),
                         new XElement("Info8", "info8")
                        )
        );

        XDocument doc = new XDocument(
            new XComment("This is a comment"),
            new XElement("Root",
                         from el in srcTree.Element("Root").Elements()
                         where ((string)el).StartsWith("data")
                         select el
                        )
        );

        Console.WriteLine(doc);
        doc.Save("C:\\example.xml");

        Console.Read();
    }
}

Output:

<!–This is a comment–>
<Root>
<Child1>data1</Child1>
<Child2>data2</Child2>
<Child3>data3</Child3>
<Child2>data4</Child2>
</Root>

http://yinyangit.wordpress.com

 Chia sẻ qua: 
Hot!
Ý kiến bạn đọc

These items will be permanently deleted and cannot be recovered. Are you sure?

Gallery

image

Maecenas viverra rutrum pulvinar

Maecenas viverra rutrum pulvinar! Aenean vehicula nulla sit amet metus aliquam et malesuada risus aliquet. Vestibulum rhoncus, dolor sit amet venenatis porta, metus purus sagittis nisl, sodales volutpat elit lorem…

Read more

Text Links

Thiết kế logo chuyên nghiệp Insky
DAFABET
W88 w88b.com/dang-ky-tai-khoan-w88
W88
Copyright © 2011 - 2012 vietshare.vn by phamkhuong102@gmail.com doanhkisi2315@gmail.com. All rights reserved.