2010-02-12 14 views
5

Tôi muốn đọc tệp xml lớn (100 + M). Do kích thước của nó, tôi không muốn tải nó trong bộ nhớ bằng cách sử dụng XElement. Tôi đang sử dụng các truy vấn LINQ-xml để phân tích cú pháp và đọc nó.Cách đọc tệp xml lớn mà không tải nó vào bộ nhớ và sử dụng XElement

Cách tốt nhất để làm điều đó là gì? Bất kỳ ví dụ về sự kết hợp của XPath hoặc XmlReader với linq-xml/XElement?

Vui lòng trợ giúp. Cảm ơn.

Trả lời

8

Có, bạn có thể kết hợp XmlReader với method XNode.ReadFrom, xem ví dụ trong tài liệu sử dụng C# để chọn lọc xử lý các nút được tìm thấy bởi XmlReader dưới dạng XElement.

+0

rực rỡ. Tôi đang phát triển một ứng dụng sẽ xử lý nhiều tệp XML 200M và XDocument đã giết tôi. điều này đã thực hiện một cải tiến lớn. cảm ơn. –

+4

Tôi nghĩ có một lỗi trong mã ví dụ trên trang tài liệu 'XNode.ReadFrom'. Câu lệnh 'XElement el = XElement.ReadFrom (reader) là XElement;' nên là 'XElement el = new XElement (reader.Name, reader.Value);' thay vào đó. Như là, đầu tiên của mỗi hai phần tử 'Child' được bỏ qua trong tệp XML mà từ đó nó đọc. –

+0

Nhận xét cuối cùng của tôi không hoàn toàn chính xác; làm việc trên này ngay bây giờ cho bản thân mình ... –

0

Chỉ cần nhớ rằng bạn sẽ phải đọc tệp tuần tự và đề cập đến anh chị em hoặc con cháu sẽ chậm nhất và không thể ở mức tồi tệ nhất. Nếu không @MartinHonnn có khóa.

+0

Câu trả lời này sẽ bị xóa và được thêm vào làm bình luận thay thế. –

5

Đoạn mã ví dụ trong tài liệu MSDN đối với phương pháp XNode.ReadFrom là như sau:

class Program 
{ 
    static IEnumerable<XElement> StreamRootChildDoc(string uri) 
    { 
     using (XmlReader reader = XmlReader.Create(uri)) 
     { 
      reader.MoveToContent(); 
      // Parse the file and display each of the nodes. 
      while (reader.Read()) 
      { 
       switch (reader.NodeType) 
       { 
        case XmlNodeType.Element: 
         if (reader.Name == "Child") 
         { 
          XElement el = XElement.ReadFrom(reader) as XElement; 
          if (el != null) 
           yield return el; 
         } 
         break; 
       } 
      } 
     } 
    } 

    static void Main(string[] args) 
    { 
     IEnumerable<string> grandChildData = 
      from el in StreamRootChildDoc("Source.xml") 
      where (int)el.Attribute("Key") > 1 
      select (string)el.Element("GrandChild"); 

     foreach (string str in grandChildData) 
      Console.WriteLine(str); 
    } 
} 

Nhưng tôi đã phát hiện ra rằng StreamRootChildDoc phương pháp trong ví dụ này cần phải được sửa đổi như sau:

static IEnumerable<XElement> StreamRootChildDoc(string uri) 
    { 
     using (XmlReader reader = XmlReader.Create(uri)) 
     { 
      reader.MoveToContent(); 
      // Parse the file and display each of the nodes. 
      while (!reader.EOF) 
      { 
       if (reader.NodeType == XmlNodeType.Element && reader.Name == "Child") 
       { 
        XElement el = XElement.ReadFrom(reader) as XElement; 
        if (el != null) 
         yield return el; 
       } 
       else 
       { 
        reader.Read(); 
       } 
      } 
     } 
    }