2011-04-09 65 views
30

我已經編寫了一個用於學習目的的任務計劃程序。目前我正在將預定任務保存爲純文本,然後使用正則表達式對其進行解析。這看起來很亂(代碼明智),並不是很連貫。XML解析 - 讀取簡單的XML文件並檢索值

我想從XML文件加載計劃的任務,而不是尋找一些解決方案,但我無法實現它的工作方式。

我寫的結構像這樣保存在我的數據的XML文件:

<Tasks> 
    <Task> 
     <Name>Shutdown</Name> 
     <Location>C:/WINDOWS/system32/shutdown.exe</Location> 
     <Arguments>-s -f -t 30</Arguments> 
     <RunWhen> 
      <Time>8:00:00 a.m.</Time> 
      <Date>18/03/2011</Date> 
      <Days> 
       <Monday>false</Monday> 
       <Tuesday>false</Tuesday> 
       <Wednesday>false</Wednesday> 
       <Thursday>false</Thursday> 
       <Friday>false</Friday> 
       <Saturday>false</Saturday> 
       <Sunday>false</Sunday> 
       <Everyday>true</Everyday> 
       <RunOnce>false</RunOnce> 
      </Days> 
     </RunWhen> 
     <Enabled>true</Enabled> 
    </Task> 
</Tasks> 

我想分析數據的方式是像這樣:

  1. 未完成任務。 xml
  2. 加載第一個Task標籤。
  3. 在該任務中檢索Name,Location和Arguments標籤的值。
  4. 然後打開RunWhen標籤並檢索時間和日期標籤的值。
  5. 之後,打開Days標籤並檢索其中每個單獨標籤的值。
  6. 檢索已啓用的值。
  7. 加載下一個任務並重復步驟3→7,直到任務中的所有任務標籤都被解析。

我很相信你能做到這樣,我就不能工作了,因爲有這麼多不同的方式來做事的XML我有點不知所措。但是到目前爲止,我最喜歡使用XPathDocument和XPathNodeIterator嗎?

如果有人能告訴我一個例子或向我解釋這將如何完成,我會很高興。

回答

41

解析XML簡單的方法是使用LINQ to XML

比如你有以下的XML文件

<library> 
    <track id="1" genre="Rap" time="3:24"> 
     <name>Who We Be RMX (feat. 2Pac)</name> 
     <artist>DMX</artist> 
     <album>The Dogz Mixtape: Who's Next?!</album> 
    </track> 
    <track id="2" genre="Rap" time="5:06"> 
     <name>Angel (ft. Regina Bell)</name> 
     <artist>DMX</artist> 
     <album>...And Then There Was X</album> 
    </track> 
    <track id="3" genre="Break Beat" time="6:16"> 
     <name>Dreaming Your Dreams</name> 
     <artist>Hybrid</artist> 
     <album>Wide Angle</album> 
    </track> 
    <track id="4" genre="Break Beat" time="9:38"> 
     <name>Finished Symphony</name> 
     <artist>Hybrid</artist> 
     <album>Wide Angle</album> 
    </track> 
<library> 

要讀取這個文件,你可以使用下面的代碼:

public void Read(string fileName) 
{ 
    XDocument doc = XDocument.Load(fileName); 

    foreach (XElement el in doc.Root.Elements()) 
    { 
     Console.WriteLine("{0} {1}", el.Name, el.Attribute("id").Value); 
     Console.WriteLine(" Attributes:"); 
     foreach (XAttribute attr in el.Attributes()) 
      Console.WriteLine(" {0}", attr); 
     Console.WriteLine(" Elements:"); 

     foreach (XElement element in el.Elements()) 
      Console.WriteLine(" {0}: {1}", element.Name, element.Value); 
    } 
} 
+1

我得到它的工作完美,謝謝堆:) – Lucidity 2011-04-09 12:22:54

+1

這真的很簡單,謝謝 – 2013-04-18 06:55:27

+6

對於那些想要複製/粘貼此代碼,還需要添加「using System.Xml.Linq;」 – VenerableAgents 2015-04-15 18:57:48

2

您是否熟悉DataSet類?

DataSet也可以load XML文檔,你可能會發現它更容易迭代。

http://msdn.microsoft.com/en-us/library/system.data.dataset.readxml.aspx

DataSet dt = new DataSet(); 
dt.ReadXml(@"c:\test.xml"); 
+2

-1:DataTable無法加載所有XML,只能匹配關係數據庫模式的XML。 – 2013-02-21 19:27:03

+0

@JohnSaunders - 照顧精心製作?我只是嘗試了上述代碼與有問題的XML文件,並讀取它沒有問題 – WraithNath 2013-03-12 16:55:27

+0

正是我所說的。 'DataSet'不能處理任意的XML。它只能處理映射到「關係」結構的XML。 ''DataSet'不適用於許多「正常」的東西,你可能想要使用XML。例如,''。關係表不能有兩個父母,所以這不適用於'DataSet'。 – 2013-03-12 17:03:22

8

我通常使用XmlDocument這一點。該接口是非常簡單的:在一個節點的所有子

var tasks = doc["Tasks"]; 

和循環:

var doc = new XmlDocument(); 
doc.LoadXml(xmlString); 

您可以訪問類似於字典的節點。

2

嘗試XmlSerialization

試試這個

[Serializable] 
public class Task 
{ 
    public string Name{get; set;} 
    public string Location {get; set;} 
    public string Arguments {get; set;} 
    public DateTime RunWhen {get; set;} 
} 

public void WriteXMl(Task task) 
{ 
    XmlSerializer serializer; 
    serializer = new XmlSerializer(typeof(Task)); 

    MemoryStream stream = new MemoryStream(); 

    StreamWriter writer = new StreamWriter(stream, Encoding.Unicode); 
    serializer.Serialize(writer, task); 

    int count = (int)stream.Length; 

    byte[] arr = new byte[count]; 
    stream.Seek(0, SeekOrigin.Begin); 

    stream.Read(arr, 0, count); 

    using (BinaryWriter binWriter=new BinaryWriter(File.Open(@"C:\Temp\Task.xml", FileMode.Create))) 
    { 
     binWriter.Write(arr); 
    } 
} 

public Task GetTask() 
{ 
    StreamReader stream = new StreamReader(@"C:\Temp\Task.xml", Encoding.Unicode); 
    return (Task)serializer.Deserialize(stream); 
}