2011-04-09 81 views
2

這裏是我的XML文件如何按屬性選擇XML節點並使用它的子節點數據?

<?xml version="1.0" encoding="utf-8" ?> 
<storage> 
<Save Name ="Lifeline"> 
<Seconds>12</Seconds> 
<Minutes>24</Minutes> 
<Hours>9</Hours> 
<Days>25</Days> 
<Months>8</Months> 
<Years>2010</Years> 
<Health>90</Health> 
<Mood>100</Mood> 
</Save> 

<Save Name ="Hellcode"> 
<Seconds>24</Seconds> 
<Minutes>48</Minutes> 
<Hours>18</Hours> 
<Days>15</Days> 
<Months>4</Months> 
<Years>1995</Years> 
<Health>50</Health> 
<Mood>50</Mood> 
</Save> 

這裏是得到的來自XML並將其加載到應用程序數據的代碼。

System.IO.StreamReader sr = new System.IO.StreamReader(@"Saves.xml"); 

System.Xml.XmlTextReader xr = new System.Xml.XmlTextReader(sr); 

System.Xml.XmlDocument save = new System.Xml.XmlDocument(); 

save.Load(xr); 


XmlNodeList saveItems = save.SelectNodes("Storage/Save"); 

XmlNode seconds = saveItems.Item(0).SelectSingleNode("Seconds"); 
sec = Int32.Parse(seconds.InnerText); 

XmlNode minutes = saveItems.Item(0).SelectSingleNode("Minutes"); 
min = Int32.Parse(minutes.InnerText); 

XmlNode hours = saveItems.Item(0).SelectSingleNode("Hours"); 
hour = Int32.Parse(hours.InnerText); 

XmlNode days = saveItems.Item(0).SelectSingleNode("Days"); 
day = Int32.Parse(days.InnerText); 

XmlNode months = saveItems.Item(0).SelectSingleNode("Months"); 
month = Int32.Parse(months.InnerText); 

XmlNode years = saveItems.Item(0).SelectSingleNode("Years"); 
year = Int32.Parse(years.InnerText); 

XmlNode health_ = saveItems.Item(0).SelectSingleNode("Health"); 
health = Int32.Parse(health_.InnerText); 

XmlNode mood_ = saveItems.Item(0).SelectSingleNode("Mood"); 
mood = Int32.Parse(mood_.InnerText); 

問題是,此代碼從「生命線」節點加載數據。我想使用一個列表框並且能夠選擇從哪個節點加載數據。

我試圖從列表框中項內容採取的字符串,然後用這樣的行

XmlNodeList saveItems = save.SelectNodes(string.Format("storage/Save[@Name = '{0}']", name)); 

變量「名」是從listboxe的項目的字符串。編譯時這段代碼給出了異常。 有人知道如何通過屬性選擇並加載該XML中的內容數據?

+1

你能提供的除外。 – 2011-04-09 19:51:22

+0

可能的重複[在C#中使用屬性讀取XML的問題](http://stackoverflow.com/questions/5606075/problem-with-reading-from-an-xml-with-attributes-in-c) – BrokenGlass 2011-04-09 19:57:05

回答

0

由於它沒有那麼多的數據,我建議加載所有信息以列表的保存(構造函數),然後從那裏用戶想使用哪一個繪圖...

至於事情不工作,我個人使用較低級別的方法來獲取我的數據,並且不容易出錯。重塑它適合你的問題有點:

int saves = 0; 

List<Saves> saveGames = new List<Saves>(); 

saveGames.Add(new Saves()); 

while (textReader.Read()) 
{ 
    if (textReader.NodeType == XmlNodeType.Element) 
     whatsNext = textReader.Name; 
    else if (textReader.NodeType == XmlNodeType.Text) 
    { 
     if (whatsNext == "name") 
     saveGames[saves].name = Convert.ToString(textReader.Value); 
     //else if statements for the rest of your attributes 
     else if (whatsNext == "Save") 
     { 
     saveGames.Add(new Saves()); 
     saves++; 
     } 
    } 
    else if (textReader.NodeType == XmlNodeType.EndElement) 
     whatsNext = ""; 
} 

基本上扔在XML文件中的一切到對象的列表和操縱該列表填寫列表框。取而代之的是保存名稱=「...」,將名稱屬性作爲保存中的第一個屬性。

代碼標記恨我。 (._)爲什麼他們打破這麼容易

+0

只需將您的代碼行縮進四個字符即可,無需額外的代碼標籤! – 2011-04-09 20:06:42

+0

我總是嘗試標籤,並得到編輯頁面周圍,哈哈。 Ty先生。 – Remm 2011-04-09 21:11:21

0

選擇節點正在返回兩個XmlNode對象。

XmlNodeList saveItems = save.SelectNodes("Storage/Save"); 

在後面的代碼你似乎是選擇的第一個與saveItems.Item(0),並正從它的值在這種情況下將與NAME =「生命線」保存節點。因此,如果您要執行saveItems.Item(1)並選擇節點及其值,那麼您將得到另一組節點。

1

如果你可以使用的XElement:

XElement xml = XElement.Load(file); 
XElement storage = xml.Element("storage"); 
XElement save = storage.Elements("Save").FirstOrDefault(e => ((string)e.Attribute("Name")) == nameWeWant); 
if(null != save) 
{ 
// do something with it 
} 

個人而言,我喜歡有一個轉換,並從的XElement隱藏主程序,詳細說明屬性的類。 IE說Save類在構造函數中接受一個XElement節點,將其保存在全局內部,並且屬性讀/寫它。

Example類:

public class MyClass 
    { 
     XElement self; 
     public MyClass(XElement self) 
     { 
     this.self = self; 
     } 

    public string Name 
    { 
     get { return (string)(self.Attribute("Name") ?? "some default value/null"); } 
     set 
     { 
     XAttribute x = source.Attribute("Name"); 
     if(null == x) 
      source.Add(new XAttribute("Name", value)); 
     else 
      x.ReplaceWith(new XAttribute("Name", value)); 
     } 
    } 
    } 

然後你就可以搜索更改爲類似:

XElement save = storage.Elements("Save") 
    .FirstOrDefault(e => new MyClass(e).Name == NameWeWant);