2009-10-14 40 views
13

Tôi đang phân tích một số lượng lớn các tập tin lớn và sau khi profiling nút cổ chai của tôi là:Làm thế nào để xây dựng XmlNodes từ XmlReader

XmlDocument doc = new XmlDocument(); 
doc.Load(filename); 

Cách tiếp cận này rất tiện dụng vì tôi có thể trích xuất các nút như thế này:

XmlNodeList nodeList = doc.SelectNodes("myXPath"); 

Tôi đang chuyển sang XmlReader, nhưng Khi tôi tìm thấy phần tử tôi cần trích xuất, tôi bị kẹt liên quan đến cách tạo XmlNode từ nó như không quá quen thuộc với XmlReader:

XmlReader xmlReader = XmlReader.Create(fileName); 

while (xmlReader.Read()) 
{ 
    //keep reading until we see my element 
    if (xmlReader.Name.Equals("myElementName") && (xmlReader.NodeType == XmlNodeType.Element)) 
    { 
     // How do I get the Xml element from the reader here? 
    } 
} 

Tôi muốn có thể tạo đối tượng List<XmlNode>. Tôi đang ở trên .NET 2.0.

Bất kỳ trợ giúp nào được đánh giá cao!

Trả lời

6

Loại XmlNode không có công cụ xây dựng công khai, do đó bạn không thể tự tạo chúng. Bạn sẽ cần phải có một XmlDocument mà bạn có thể sử dụng để tạo ra chúng:

XmlDocument doc = new XmlDocument(); 
while (xmlReader.Read()) 
{ 
    //keep reading until we see my element 
    if (xmlReader.Name.Equals("myElementName") && (xmlReader.NodeType == XmlNodeType.Element)) 
    { 
     // How do I get the Xml element from the reader here? 
     XmlNode myNode = doc.CreateNode(XmlNodeType.Element, xmlReader.Name, ""); 
     nodeList.Add(myNode); 
    }   
} 
+1

dường như tạo các nút trống? – JohnIdol

+0

Có, trừ khi bạn thêm bất cứ thứ gì vào các phần tử (bằng cách gán một cái gì đó cho thuộc tính 'InnerText'), chúng sẽ rỗng. –

+0

oh yep - có vẻ hiển nhiên ngay từ khi tôi chỉ chuyển tên phần tử vào, nhờ – JohnIdol

5

XmlReaderXmlDocument có một cách rất rõ rệt của chế biến. XmlReader không giữ gì trong bộ nhớ và sử dụng cách tiếp cận chuyển tiếp chỉ trái ngược với việc xây dựng một cây DOM đầy đủ trong bộ nhớ cho XmlDocument. Nó là hữu ích khi hiệu suất là một vấn đề, nhưng nó cũng yêu cầu bạn viết ứng dụng của bạn một cách khác nhau: thay vì sử dụng XmlNode, bạn không giữ bất cứ điều gì và chỉ xử lý "khi đang di chuyển": nghĩa là khi một phần tử đi qua mà bạn cần , bạn làm điều gì đó. Điều này gần với cách tiếp cận SAX, nhưng không có mô hình gọi lại.

Câu trả lời cho "cách nhận XmlElement" là: bạn sẽ phải xây dựng chúng từ đầu dựa trên thông tin từ người đọc. Điều này, thật không may, bất chấp sự tăng hiệu suất. Nó thường là tốt hơn để ngăn chặn bằng cách sử dụng phương pháp tiếp cận DOM hoàn toàn một khi bạn chuyển sang XmlReader, trừ khi cho một vài trường hợp riêng biệt.

Ngoài ra, cách "rất tiện dụng" để trích xuất các nút bằng XPath (SelectNodes là những gì bạn hiển thị ở trên) không thể được sử dụng ở đây: XPath yêu cầu cây DOM. Xem xét phương pháp tiếp cận này một cách tiếp cận lọc: bạn có thể thêm bộ lọc vào XmlReader và yêu cầu nó bỏ qua các nút nhất định hoặc đọc cho đến khi một nút nhất định. Điều này cực kỳ nhanh, nhưng một cách suy nghĩ khác.

4

Sử dụng XmlDocument.ReadNode cho phương pháp này. Đặt XmlReader trong sử dụng câu lệnh và sử dụng XmlReader.LocalName thay vì Tên để xóa tiền tố không gian tên.

1

Tôi đã sử dụng workaround sau khi tôi đã để chèn dữ liệu từ một XmlReader thành một XmlDocumenht:

XmlReader rdr = cmd.ExecuteXmlReader(); 

XmlDocument doc = new XmlDocument(); 

// create a container node for our resultset 
XmlElement root = doc.CreateElement("QueryRoot"); 
doc.AppendChild(root); 

StringBuilder xmlBody = new StringBuilder(); 

while(rdr.Read()) 
{ 
    xmlBody.Append(rdr.ReadOuterXml()); 
} 

root.InnerXml = xmlBody.ToString(); 
12

Tại sao không chỉ thực hiện như sau?

XmlDocument doc = new XmlDocument(); 
XmlNode node = doc.ReadNode(reader); 
+0

Đã được trả lời. Xem http://stackoverflow.com/questions/1566192/how-to-build-xmlnodes-from-xmlreader/1566333#1566333. –

+0

Đây là câu trả lời đúng vì câu trả lời còn lại để lại các nút trống! –

0

Đây là cách tiếp cận của tôi:

public static IEnumerable<XmlNode> StreamNodes(
    string path, 
    string[] tagNames) 
{    
    var doc = new XmlDocument();    
    using (XmlReader xr = XmlReader.Create(path)) 
    { 
     xr.MoveToContent(); 
     while (true) { 
      if (xr.NodeType == XmlNodeType.Element && 
       tagNames.Contains(xr.Name)) 
      { 
       var node = doc.ReadNode(xr); 
       yield return node; 
      } 
      else 
      { 
       if (!xr.Read()) 
       { 
        break; 
       } 
      } 
     } 
     xr.Close(); 
    }       
} 
// Used like this: 
foreach (var el in StreamNodes("orders.xml", new string[]{"order"})) 
{ 
    .... 
} 

Các nút sau đó có thể được nhập khẩu vào tài liệu khác để chế biến tiếp.

Các vấn đề liên quan