2013-01-20 43 views
-1

我遞歸地想要顯示xml節點。但不幸的是它不起作用。輸出只是xml文件的第一個元素。爲什麼?我想遞歸列出xml中的節點

public string GetOutline(int indentLevel, XmlNode xnod) 
{ 
     StringBuilder result = new StringBuilder(); 
     XmlNode xnodWorking; 

     result = result.AppendLine(new string('-', indentLevel * 2) + xnod.Name); 

     if (xnod.NodeType == XmlNodeType.Element) 
     { 
      if (xnod.HasChildNodes) 
      { 
       xnodWorking = xnod.FirstChild; 
       while (xnodWorking != null) 
       { 
        GetOutline(indentLevel + 1, xnodWorking); 
        xnodWorking = xnodWorking.NextSibling; 

       } 
      } 

     } 
     return result.ToString(); 
} 

下面的代碼調用該函數。 XML文件開始<Videos>然後<Video> ...等...

private void button2_Click(object sender, EventArgs e) 
{ 
     SaveFileDialog fDialog = new SaveFileDialog(); 
     fDialog.Title = "Save XML File"; 
     fDialog.FileName = "drzewo.xml"; 
     fDialog.CheckFileExists = false; 
     fDialog.InitialDirectory = @"C:\Users\Piotrek\Desktop"; 

     if (fDialog.ShowDialog() == DialogResult.OK) 
     { 
      using (var newXmlFile = File.Create(fDialog.FileName)); 
      { 
       string xmlTree = fDialog.FileName.ToString(); 

       XmlDocument xdoc = new XmlDocument(); 
       xdoc.Load(XML); 

       XmlNode xnodDE = xdoc.DocumentElement; 

       textBox2.Text = GetOutline(0, xnodDE); 

       //StringBuilder result = new StringBuilder(); 

       /* 
       foreach (var childelement in xdoc.DescendantNodes().OfType<XElement>() 
        .Select(x => x.Name).Distinct()) 
       { 
        result.Append(childelement + Environment.NewLine); 

       } 
       textBox2.Text = result.ToString(); 
       */ 

       using (StreamWriter sw = File.AppendText(xmlTree)) 
       { 
        sw.Write(textBox2.Text); 
       } 
      } 
} 

XML內容:

<Videos> 
    <Video> 
    <Title>The Distinguished Gentleman</Title> 
    <Director>Jonathan Lynn</Director> 
    <Actors> 
     <Actor>Eddie Murphy</Actor> 
     <Actor>Lane Smith</Actor> 
     <Actor>Sheryl Lee Ralph</Actor> 
     <Actor>Joe Don Baker</Actor> 
    </Actors> 
    <Length>112 Minutes</Length> 
    <Format>DVD</Format> 
    <Rating>R</Rating> 
    </Video> 
    <Video> 
    <Title>Her Alibi</Title> 
    <Director>Bruce Beresford</Director> 
    <Length>94 Mins</Length> 
    <Format>DVD</Format> 
    <Rating>PG-13</Rating> 
    </Video> 
</Videos> 
+0

你能告訴我們的代碼,其中你最初調用'GetOutline'? – JLRishe

回答

0

你需要閱讀所有在線文檔線蒙山一個對每個或同時指令

XmlReader reader = XmlReader.Create(your xml file); 
     reader.MoveToContent(); 

     while (reader.Read()) 
     { 
      // your code 
     } 

     reader.Close(); 

不是最好的方式,儘量看看還對LINQ爲xml

+0

我試圖用linq來做到這一點,但我被卡住了遞歸獲取XElement的下一個元素(沒有方法)。我結束了使用System.xml :( – Peter

+0

@Peter可以發佈xml內容嗎? – Yeurl

+0

XmlException是unhandle。沒有根元素。 – Peter

0

您沒有做任何事情來將遞歸調用的結果添加到您正在構建的字符串中。你需要這樣做:

result.Append(GetOutline(indentLevel + 1, xnodWorking)); 

而這種修改應避免文本節點和節點具有相同的名稱:

public string GetOutline(int indentLevel, XmlNode xnod) 
{ 
    StringBuilder result = new StringBuilder(); 
    XmlNode xnodWorking; 

    result = result.AppendLine(new string('-', indentLevel * 2) + xnod.Name); 

    if (xnod.HasChildNodes) 
    { 
     List<string> foundElements = new List<string>(); 
     xnodWorking = xnod.FirstChild; 
     while (xnodWorking != null) 
     { 
      if(xnodworking.NodeType == XmlNodeType.Element && !foundElements.Contains(xnodworking.Name)) 
      { 
       result.Append(GetOutline(indentLevel + 1, xnodWorking)); 
       foundElements.Add(xnodworking.Name); 
      } 
      xnodWorking = xnodWorking.NextSibling; 
     } 
    } 

    return result.ToString(); 
}      
+0

上面的情況如何?這將防止重複某個特定父級的子節點並避免文本節點。 – JLRishe

0

嘗試

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

using System.Xml; 
using System.Xml.Linq; 

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

     //Load xml 
     XDocument xdoc = XDocument.Load("test.xml"); 

     //Run query 
     var lv1s = from lv1 in xdoc.Descendants("Video") 
        select new 
        { 
         title = lv1.Element("Title").Value 
        }; 

     //Loop through results 
     foreach (var lv1 in lv1s) 
     { 
      Console.WriteLine(lv1.title); 
     } 

     Console.ReadLine(); 
    } 
} 
}