2011-04-09 63 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); 
}