2013-04-12 27 views
12

Tôi đã tạo ra một tập tin Xml với nội dung ví dụ như sau:Đọc nhiều nút con của tập tin xml

<?xml version="1.0" encoding="utf-8" ?> 
<Periods> 
    <PeriodGroup name="HER"> 
    <Period> 
     <PeriodName>Prehistoric</PeriodName> 
     <StartDate>-500000</StartDate> 
     <EndDate>43</EndDate> 
    </Period> 
    <Period> 
     <PeriodName>Iron Age</PeriodName> 
     <StartDate>-800</StartDate> 
     <EndDate>43</EndDate> 
    </Period> 
    <Period> 
     <PeriodName>Roman</PeriodName> 
     <StartDate>43</StartDate> 
     <EndDate>410</EndDate> 
    </Period> 
    </PeriodGroup> 
    <PeriodGroup name="CAFG"> 
    <Period> 
     <PeriodName>Prehistoric</PeriodName> 
     <StartDate>-500000</StartDate> 
     <EndDate>43</EndDate> 
    </Period> 
    <Period> 
     <PeriodName>Roman</PeriodName> 
     <StartDate>43</StartDate> 
     <EndDate>410</EndDate> 
    </Period> 
    <Period> 
     <PeriodName>Anglo-Saxon</PeriodName> 
     <StartDate>410</StartDate> 
     <EndDate>800</EndDate> 
    </Period> 
    </PeriodGroup> 
</Periods> 

tôi cần phải có khả năng đọc các nút con Thời gian trong vòng một PeriodGroup chọn. Tôi đoán PeriodName có thể là một thuộc tính của Period nếu điều đó hợp lý hơn.

Tôi đã xem tải các ví dụ nhưng dường như không có gì đúng và dường như có hàng tá phương pháp khác nhau, một số sử dụng XmlReader, một số XmlTextReader và một số không sử dụng. Vì đây là lần đầu tiên tôi đọc một tệp Xml, tôi nghĩ tôi sẽ hỏi liệu có ai có thể cho tôi một con trỏ hay không. Tôi đã có một cái gì đó làm việc chỉ để thử những điều trên, nhưng nó cảm thấy clunky. Tôi đang sử dụng VS2010 và C#. Ngoài ra, tôi thấy rất nhiều người đang sử dụng LINQ-Xml, vì vậy tôi đánh giá cao những ưu và khuyết điểm của việc sử dụng phương pháp này.

string PG = "HER"; 
XmlDocument doc = new XmlDocument(); 
doc.Load(Server.MapPath("./Xml/XmlFile.xml")); 
string text = string.Empty; 
XmlNodeList xnl = doc.SelectNodes("/Periods/PeriodGroup"); 
foreach (XmlNode node in xnl) 
{ 
    text = node.Attributes["name"].InnerText; 
    if (text == PG) 
    { 
     XmlNodeList xnl2 = doc.SelectNodes("/Periods/PeriodGroup/Period"); 
     foreach (XmlNode node2 in xnl2) 
     { 
      text = text + "<br>" + node2["PeriodName"].InnerText; 
      text = text + "<br>" + node2["StartDate"].InnerText; 
      text = text + "<br>" + node2["EndDate"].InnerText; 
     } 
    } 
    Response.Write(text); 
} 

Trả lời

11

Bạn có thể sử dụng một cách tiếp cận XPath như vậy:

XmlNodeList xnl = doc.SelectNodes(string.Format("/Periods/PeriodGroup[@name='{0}']/Period", PG)); 

Mặc dù thích LINQ to XML cho nó dễ đọc.

Điều này sẽ trả về các nút con số Period dựa trên thuộc tính PeriodGroupname được cung cấp, ví dụ: HER:

XDocument xml = XDocument.Load(HttpContext.Current.Server.MapPath(FileLoc)); 

var nodes = (from n in xml.Descendants("Periods") 
      where n.Element("PeriodGroup").Attribute("name").Value == "HER" 
      select n.Element("PeriodGroup").Descendants().Elements()).ToList(); 

Kết quả:

<PeriodName>Prehistoric</PeriodName> 
<StartDate>-500000</StartDate> 
<EndDate>43</EndDate> 

<PeriodName>Iron Age</PeriodName> 
<StartDate>-800</StartDate> 
<EndDate>43</EndDate> 

<PeriodName>Roman</PeriodName> 
<StartDate>43</StartDate> 
<EndDate>410</EndDate> 

Truy vấn là khá đơn giản

from n in xml.Descendants("Periods") 

sẽ trả về một bộ sưu tập của các yếu tố hậu duệ cho các phần tử Periods. Sau đó chúng tôi sử dụng where để lọc bộ sưu tập này của các nút dựa trên giá trị thuộc tính:

where n.Element("PeriodGroup").Attribute("name").Value == "HER" 

sau đó sẽ lọc xuống bộ sưu tập để PeriodGroup yếu tố mà có một thuộc tính name với một giá trị của HER

Cuối cùng, chúng tôi chọn các yếu tố PeriodGroup và làm cho nó là nút hậu duệ

select n.Element("PeriodGroup").Descendants().Elements() 

EDIT (Xem ý kiến)

Vì kết quả của biểu thức này chỉ là một truy vấn, chúng tôi sử dụng .ToList() để liệt kê bộ sưu tập và trả lại đối tượng chứa các giá trị bạn cần.Bạn cũng có thể tạo ra các kiểu nặc danh để lưu trữ các giá trị phần tử ví dụ:

var nodes = (from n in xml.Descendants("Period"). 
      Where(r => r.Parent.Attribute("name").Value == "HER") 
      select new 
      { 
        PeriodName = (string)n.Element("PeriodName").Value, 
        StartDate = (string)n.Element("StartDate").Value, 
        EndDate = (string)n.Element("EndDate").Value 
      }).ToList(); 

//Crude demonstration of how you can reference each specific element in the result 
//I would recommend using a stringbuilder here.. 
foreach (var n in nodes) 
{ 
     text += "<br>" + n.PeriodName; 
     text += "<br>" + n.StartDate; 
     text += "<br>" + n.EndDate; 
} 

Đây là những gì đối tượng nodes sẽ trông giống như sau khi truy vấn đã chạy:

enter image description here

+0

Bạn có muốn mở rộng LINQ của mình một chút vì tôi chưa bao giờ sử dụng nó. Sử dụng 'XElement xml = XElement.Load (Server.MapPath (" ./ Xml/XmlFile.xml "));' các nút không được trả về trong các nút var. –

+0

Tôi nghĩ rằng bạn có nghĩa là 'XDocument' ví dụ:' XDocument xml = XDocument.Load (HttpContext.Current.Server.MapPath (FileLoc)); ' – DGibbs

+0

Thêm một giải thích ngắn gọn về truy vấn – DGibbs

4

Kể từ khi phương pháp XmlDocument.SelectNodes thực sự chấp nhận một biểu thức XPath, bạn đang tự do đi như thế này:

XmlNodeList xnl = doc.SelectNodes("/Periods/PeriodGroup[@name='" + PG + "']/Period"); 
foreach (XmlNode node in xnl) { 
    // Every node here is a <Period> child of the relevant <PeriodGroup>. 
} 

Bạn có thể tìm hiểu thêm về XPath tại w3schools.

+0

@DGibbs đã mở rộng câu trả lời của bạn, nhưng nó vẫn hoạt động, vì vậy cảm ơn. –

0

đi qua

này
public static void XMLNodeCheck(XmlNode xmlNode) 
    { 
     if (xmlNode.HasChildNodes) 
     { 
      foreach (XmlNode node in xmlNode) 
      { 
       if (node.HasChildNodes) 
       { 
        Console.WriteLine(node.Name); 
        if (node.Attributes.Count!=0) 
        { 
         foreach (XmlAttribute att in node.Attributes) 
         { 
          Console.WriteLine("----------" + att.Name + "----------" + att.Value); 
         } 
        } 

        XMLNodeCheck(node);//recursive function 
       } 
       else 
       { 
        if (!node.Equals(XmlNodeType.Element)) 
        { 
         Console.WriteLine(node.InnerText); 
        } 

       } 
      } 
     } 
    } 
+0

Không có câu hỏi nào ở đây, chúng tôi không thể trả lời nếu bạn không hỏi :) – meta

+0

tôi cung cấp giải pháp only.not other else @meta – chandu

+0

up, sorry;) Tôi đã nhầm lẫn – meta

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