2012-11-30 25 views
5

Tôi đang viết lại một số mã sử dụng XmlDocument để phân tích cú pháp một số XML. Tôi muốn sử dụng một XmlReader thay vì để xem tôi có thể nhận được một số cải tiến hiệu suất. Cấu trúc của XML trông như thế này:Sử dụng lớp XmlReader để phân tích XML bằng các phần tử có cùng tên

<items> 
    <item id="1" desc="one"> 
     <itemBody date="2012-11-12" /> 
    </item> 
    <item id="2" desc="two"> 
     <itemBody date="2012-11-13" /> 
    </item> 
    <item id="3" desc="three"> 
     <itemBody date="2012-11-14" /> 
    </item> 
    <item id="4" desc="four"> 
     <itemBody date="2012-11-15" /> 
    </item> 
</items> 

Về cơ bản, tôi cần phải lặp qua tất cả các yếu tố <item>. Như tôi đã nói, các mã cũ làm việc như thế này:

XmlDocument document = new XmlDocument(); 

// load XML into XmlDocument 
document.LoadXml(xml); 

// use xpath to split into individual item 
string xPath = @"items/item"; 
XmlNodeList nodeList = document.SelectNodes(xPath); 

// loop through each item 
for (int nodeIndex = 0; nodeIndex < nodeList.Count; nodeIndex++) 
{ 
    // do something with the XmlNode 
    nodeList[nodeIndex]; 
} 

này hoạt động tốt, nhưng tôi nghĩ rằng sử dụng một XmlReader sẽ nhanh hơn. Vì vậy, tôi đã viết điều này:

XmlReader xmlReader = XmlReader.Create(new StringReader(xml)); 

while (xmlReader.Read()) 
{      
    if (xmlReader.Name.Equals("item") && (xmlReader.NodeType == XmlNodeType.Element)) 
    { 
     string id = xmlReader.GetAttribute("id");     
     string desc = xmlReader.GetAttribute("desc"); 
     string elementXml = xmlReader.ReadOuterXml(); 
    } 
} 

Tuy nhiên, mã này chỉ đọc phần tử <item> đầu tiên. ReadOuterXml() đang phá vỡ vòng lặp. Có ai biết làm thế nào để có được xung quanh này? Hay kiểu phân tích cú pháp này không thể thực hiện được với XmlReader? Tôi đã phải làm điều này sử dụng phiên bản .NET 2 :(Vì vậy, tôi không thể sử dụng LINQ

+1

Điều gì xảy ra sau yếu tố đầu tiên? Bạn đã sửa lỗi gì? Mã gốc của bạn có thực sự * quá chậm không? (Không viết mã khó hơn chỉ để * có khả năng * làm cho mọi thứ nhanh hơn nếu chúng đã đủ nhanh ...) –

+0

đây không phải là một phản hồi, nhưng ... bạn có sử dụng xsd2code không? Rất hữu ích khi phân tích cú pháp xml thành các lớp –

+0

Giá trị trả về của giá trị này là bao nhiêu? new StringReader (xml) .ReadToEnd() – laszlokiss88

Trả lời

1

sau đây dường như làm việc: -.

 StringBuilder xml = new StringBuilder(); 

     xml.Append("<items>"); 
     xml.Append("<item id=\"1\" desc=\"one\">"); 
     xml.Append("<itembody id=\"10\"/>"); 
     xml.Append("</item>"); 
     xml.Append("<item id=\"2\" desc=\"two\">"); 
     xml.Append("<itembody id=\"20\"/>"); 
     xml.Append("</item>"); 
     xml.Append("<item id=\"3\" desc=\"three\">"); 
     xml.Append("<itembody id=\"30\"/>"); 
     xml.Append("</item>"); 
     xml.Append("</items>"); 

     using (XmlTextReader tr = new XmlTextReader(new StringReader(xml.ToString()))) 
     { 
      bool canRead = tr.Read(); 
      while (canRead) 
      { 
       if ((tr.Name == "item") && tr.IsStartElement()) 
       { 
        Console.WriteLine(tr.GetAttribute("id")); 
        Console.WriteLine(tr.GetAttribute("desc")); 
        string outerxml = tr.ReadOuterXml(); 
        Console.WriteLine(outerxml); 

        canRead = (outerxml != string.Empty); 
       } 
       else 
       { 
        canRead = tr.Read(); 
       } 
      } 
     } 
4

Chỉ cần kiểm tra mã của bạn trong LinqPad hoạt động tốt

var xml = @"<items> 
    <item id='1' desc='one' /> 
    <item id='2' desc='two' /> 
    <item id='3' desc='three' /> 
    <item id='4' desc='four' /> 
</items>"; 
XmlReader xmlReader = XmlReader.Create(new StringReader(xml)); 

while (xmlReader.Read()) 
{ 
    if (xmlReader.Name.Equals("item") && (xmlReader.NodeType == XmlNodeType.Element)) 
    { 
     string id = xmlReader.GetAttribute("id");    
     string desc = xmlReader.GetAttribute("desc"); 
     Console.WriteLine("{0} {1}", id, desc); 
    } 
} 

Output:...

1 one 
2 two 
3 three 
4 four 

có lẽ có cái gì đó sai với XML của bạn

+0

Và bạn chắc chắn rằng bạn đang sử dụng thư viện .NET 2.0? –

+0

Xin chào Oleg, tôi vừa cập nhật câu hỏi của mình. Tôi quên đề cập đến rằng tôi cần phải trích xuất phần tử xml. –

0

Nếu bạn có thể sử dụng LINQ, dưới đây là một cách khác:

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

     const string xml = @"<items> 
          <item id='1' desc='one'> 
          <itemBody date='2012-11-12' /> 
          </item> 
          <item id='2' desc='two'> 
          <itemBody date='2012-11-13' /> 
          </item> 
          <item id='3' desc='three'> 
          <itemBody date='2012-11-14' /> 
          </item> 
          <item id='4' desc='four'> 
          <itemBody date='2012-11-15' /> 
          </item> 
         </items>"; 

     var xmlReader = XmlReader.Create(new StringReader(xml)); 

     XElement element = XElement.Load(xmlReader, LoadOptions.SetBaseUri); 

     IEnumerable<XElement> items = element.DescendantsAndSelf("item"); 

     foreach (var xElement in items) 
     { 
      string id = GetAttributeValue("id", xElement); 
      string desc = GetAttributeValue("desc", xElement); 
      string itemBody = GetElementValue("itemBody", "date", xElement); 

      Console.WriteLine("id = {0}, desc = {1}, date = {2}", id, desc, itemBody); 
     } 

     Console.ReadLine(); 
    } 

    private static string GetElementValue(string elementName, string attributeName, XElement element) 
    { 
     XElement xElement = element.Element(elementName); 

     string value = string.Empty; 

     if (xElement != null) 
     { 
      XAttribute xAttribute = xElement.Attribute(attributeName); 

      if (xAttribute != null) 
      { 
       value = xAttribute.Value; 
      } 
     } 

     return value; 
    } 

    private static string GetAttributeValue(string attributeName, XElement element) 
    { 
     XAttribute xAttribute = element.Attribute(attributeName); 

     string value = string.Empty; 
     if (xAttribute != null) 
     { 
      value = xAttribute.Value; 
     } 

     return value; 
    } 
} 
+0

Xin chào Justin, cảm ơn vì câu trả lời nhưng như tôi đã nói trong câu hỏi của mình, tôi phải làm điều này bằng .NET phiên bản 2: (Vì vậy, tôi không thể sử dụng LINQ. –

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