2009-02-09 44 views
6

Tôi có nhiều tệp XHTML lớn được cập nhật theo cách thủ công. Trong giai đoạn xem xét các bản cập nhật, tôi muốn kiểm tra lập trình độ chính xác của các tệp. Tôi hiện đang sử dụng XmlReader, nhưng thời gian được yêu cầu trên CPU trung bình dài hơn tôi dự kiến.Cách nhanh nhất để lập trình kiểm tra tính hợp lý của các tệp XML trong C# là gì?

Các tệp XHTML có kích thước từ 4KB đến 40KB và việc xác minh mất vài giây cho mỗi tệp. Kiểm tra là cần thiết nhưng tôi muốn giữ thời gian càng ngắn càng tốt khi kiểm tra được thực hiện trong khi các tập tin đang được đọc vào bước quá trình tiếp theo.

Có cách nào nhanh hơn để thực hiện kiểm tra định dạng XML đơn giản không? Có thể sử dụng thư viện XML bên ngoài?


tôi có thể xác nhận rằng việc chứng thực "thường xuyên" nội dung dựa trên XML là nhanh như chớp bằng cách sử dụng XmlReader, và như đề xuất các vấn đề dường như có liên quan đến một thực tế là XHTML DTD được đọc mỗi lần một tập tin được xác nhận.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

Lưu ý rằng ngoài các DTD, file .ent (xhtml-lat1.ent, xhtml-symbol.ent, xhtml-special.ent) tương ứng cũng được tải xuống.

Vì bỏ qua DTD hoàn toàn không thực sự là một tùy chọn cho XHTML vì sự hợp thành chặt chẽ được liên kết chặt chẽ với các thực thể HTML được phép (ví dụ: & nbsp; sẽ kịp thời giới thiệu lỗi xác thực khi chúng tôi bỏ qua DTD).


Vấn đề đã được giải quyết bằng cách sử dụng một tùy chỉnh XmlResolver như đề xuất, phối hợp với các địa phương bản (nhúng) của cả DTD và các file thực thể.

Tôi sẽ đăng các giải pháp ở đây một lần tôi dọn dẹp mã

+0

Tôi đang gặp một vấn đề tương tự. Bạn có nhớ gửi giải pháp mã của bạn cho điều này không? – STLDeveloper

+0

@STLDeveloper Tôi đã thực hiện đề xuất trong đoạn mã sau (VB.NET): [ValidateXMLClass.vb] (https://visualqa.codeplex.com/SourceControl/latest#visualQA/ValidateXMLClass.vb). Các tệp .dtd, .ent và .mod được yêu cầu được (cục bộ) được bao gồm dưới dạng tài nguyên được nhúng để xác thực tăng tốc. Mã được gọi là như sau: 'Dim validateFile Là Mới ValidateXMLClass validateFile.fileIn = tgtFile Nếu Not validateFile.wellFormed Then ...' – barry

+0

Cảm ơn bạn đã tạo mã khả dụng sau một thời gian dài đã trôi qua từ câu hỏi ban đầu của bạn. – STLDeveloper

Trả lời

5

Tôi mong rằng XmlReader với while(reader.Read)() {} sẽ là nhanh nhất quản lý cách tiếp cận. Chắc chắn không nên dùng giây để đọc 40KB ... phương pháp nhập liệu bạn đang sử dụng là gì?

Bạn có lẽ có một số thực thể bên ngoài (lược đồ, v.v) để giải quyết không? Nếu vậy, bạn có thể viết một tùy chỉnh XmlResolver (thiết lập thông qua XmlReaderSettings) có sử dụng lược đồ được lưu cục bộ chứ không phải là một từ xa lấy ...

Sau đây không ~ 300KB hầu như ngay lập tức:

using(MemoryStream ms = new MemoryStream()) { 
     XmlWriterSettings settings = new XmlWriterSettings(); 
     settings.CloseOutput = false; 
     using (XmlWriter writer = XmlWriter.Create(ms, settings)) 
     { 
      writer.WriteStartElement("xml"); 
      for (int i = 0; i < 15000; i++) 
      { 
       writer.WriteElementString("value", i.ToString()); 
      } 
      writer.WriteEndElement(); 
     } 
     Console.WriteLine(ms.Length + " bytes"); 
     ms.Position = 0; 
     int nodes = 0; 
     Stopwatch watch = Stopwatch.StartNew(); 
     using (XmlReader reader = XmlReader.Create(ms)) 
     { 
      while (reader.Read()) { nodes++; } 
     } 
     watch.Stop(); 
     Console.WriteLine("{0} nodes in {1}ms", nodes, 
      watch.ElapsedMilliseconds); 
    } 
+0

Đây là cơ bản những gì tôi đang sử dụng bây giờ. Tôi đang đọc các tập tin trực tiếp (tôi cũng đã cố gắng đầu tiên đọc chúng vào một FileStream, nhưng điều này không thay đổi nhiều). Tôi đặt XmlWriterSettings .ProhibitDtd thành False. – barry

+0

Tôi sẽ xem xét và kiểm tra xem sự cố có nằm trong DTD và không gian tên được tham chiếu hay không. – barry

+0

Giống như bạn đã chỉ ra vấn đề có vẻ là XTD DTD. barry

2

Tạo đối tượng XmlReader bằng cách truyền trong đối tượng XmlReaderSettings có đối tượng ConformanceLevel.Document.

Điều này sẽ xác thực tính hợp lệ.

Điều này MSDN article nên giải thích chi tiết.

+0

Tôi đã thử thêm ConformanceLevel.Document cho các thiết lập, nhưng không có sự gia tăng tốc độ đáng chú ý. – barry

+0

Đây là một trong những phương pháp nhanh nhất. Như Marc ngụ ý, vấn đề tốc độ của bạn có thể do một số lý do khác. Bạn nên chỉnh sửa bài đăng của mình để bao gồm mã bạn đang sử dụng. – Cerebrus

1

Trên máy tính xách tay khá thông thường của tôi, đọc tài liệu XML 250K từ đầu đến cuối với số XmlReader mất 6 mili giây. Một cái gì đó khác ngoài việc phân tích cú pháp XML là thủ phạm.

+0

Cảm ơn, vấn đề có thể là DTD được đề xuất đang được sử dụng cho mọi séc. – barry

0

Như những người khác đã đề cập, nút cổ chai có nhiều khả năng không phải là XmlReader.

Kiểm tra xem bạn sẽ không xảy ra nhiều chuỗi nối không có trình tạo chuỗi.

Điều đó thực sự có thể làm nuke hiệu suất của bạn.

+0

Vấn đề có vẻ là trong DTD được đọc lại mọi kiểm tra (khi sử dụng các tệp XML thông thường thay vì tệp XHTML kiểm tra chạy nhanh như mong đợi). – barry

0

Cá nhân, tôi khá lười biếng ... vì vậy tôi tìm kiếm các thư viện .NET đã giải quyết được sự cố. Hãy thử sử dụng chức năng DataSet.ReadXML() và bắt các ngoại lệ. Nó thực hiện một công việc khá tuyệt vời để giải thích các lỗi định dạng XML.

1

tôi biết im hoại đăng tải nhưng tôi nghĩ rằng đây có thể là một giải pháp

  1. sử dụng HTML Tidy để xóa xml của bạn. đặt tùy chọn xóa loại tài liệu
  2. rồi đọc xhtml/xml được tạo từ ngăn xếp.

đây là một mã tương tự

public void GetDocumentStructure(int documentID) 
    { 
     string scmRepoPath = ConfigurationManager.AppSettings["SCMRepositoryFolder"]; 
     string docFilePath = scmRepoPath + "\\" + documentID.ToString() + ".xml"; 

     string docFilePath2 = scmRepoPath + "\\" + documentID.ToString() + "_clean.xml"; 

     Tidy tidy = new Tidy(); 
     tidy.Options.MakeClean = true; 
     tidy.Options.NumEntities = true; 
     tidy.Options.Xhtml = true; 
     // this option removes the DTD on the generated output of Tidy 
     tidy.Options.DocType = DocType.Omit; 

     FileStream input = new FileStream(docFilePath, FileMode.Open);    
     MemoryStream output = new MemoryStream(); 
     TidyMessageCollection msgs = new TidyMessageCollection(); 
     tidy.Parse(input, output, msgs);    
     output.Seek(0, SeekOrigin.Begin); 

     XmlReader rd = XmlReader.Create(output);    
     int node = 0; 

     System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew(); 
     while (rd.Read()) 
     {     
      ++node;     
     } 
     watch.Stop(); 

     Console.WriteLine("Duration was : " + watch.Elapsed.ToString()); 
    } 
Các vấn đề liên quan