2013-01-21 51 views
1

我正在加载一个XML文件,获取某些节点的值,然后将这些值设置为一个对象。XElement.element()有时返回null

问题是,虽然我可以进入每个节点,但我无法获得它的值:它只是返回null。在Google和SO中搜索我发现了几个线程,通常这是一个命名空间的问题。所以我在XML文件和代码中设置了一个命名空间来处理它。这是现在,当事情变得有趣:

  • 如果所有的节点,但最后一个前缀(在我的代码)与命名空间,所有的人都被设置除了特定的一种,其给出了一个ArgumentNullException(tabla不接受某些属性的空值)。这似乎是预期的行为。
  • 如果我更正了最后一行并设置了命名空间(因为它应该是),那么在FIRST节点上引发异常。

这是XML:

<?xml version="1.0" encoding="utf-8"?> 
<root xmlns="http://daniel.ponticelli.com/ns/dataExport"> 
    <PollInstance> 
    <Poll_Instance_id>1</Poll_Instance_id> 
    <POLL_description>Mes 1</POLL_description> 
    <dt_start>01/09/2012 12:00:00 a.m.</dt_start> 
    <dt_end>30/09/2012 12:00:00 a.m.</dt_end> 
    <POLL_status>0</POLL_status> 
    <dt_created>03/09/2012 09:50:36 a.m.</dt_created> 
    <dt_updated>03/09/2012 09:50:36 a.m.</dt_updated> 
    <id_original_clone>0</id_original_clone> 
    <target_locs>0</target_locs> 
    <id_poll>1</id_poll> 
    </PollInstance> 
</root> 

这是有最后一个元素没有命名空间中的 “错误” 的代码:

XElement instancia = xml.Descendants().First(); 
XNamespace ra = "http://daniel.ponticelli.com/ns/dataExport"; 

tabla.Poll_Instance_id = (int)instancia.Element(ra + "Poll_Instance_id"); 
tabla.POLL_description = (string)instancia.Element(ra + "POLL_description"); 
tabla.dt_start = DateTime.Parse((string)instancia.Element(ra + "dt_start")); 
tabla.dt_end = DateTime.Parse((string)instancia.Element(ra + "dt_end")); 
tabla.POLL_status = (int)instancia.Element(ra + "POLL_status"); 
tabla.dt_created = DateTime.Parse((string)instancia.Element(ra + "dt_created")); 
tabla.dt_updated = DateTime.Parse((string)instancia.Element(ra + "dt_updated")); 
tabla.id_original_clone = (int)instancia.Element(ra + "id_original_clone"); 
tabla.target_locs = (int)instancia.Element(ra + "target_locs"); 
tabla.id_poll = (int)instancia.Element("id_poll"); 

上面的代码提供了有关异常最后一行。

现在,这是“正确”的代码与命名空间为前缀的所有元素:

XElement instancia = xml.Descendants().First(); 
XNamespace ra = "http://daniel.ponticelli.com/ns/dataExport"; 

tabla.Poll_Instance_id = (int)instancia.Element(ra + "Poll_Instance_id"); 
tabla.POLL_description = (string)instancia.Element(ra + "POLL_description"); 
tabla.dt_start = DateTime.Parse((string)instancia.Element(ra + "dt_start")); 
tabla.dt_end = DateTime.Parse((string)instancia.Element(ra + "dt_end")); 
tabla.POLL_status = (int)instancia.Element(ra + "POLL_status"); 
tabla.dt_created = DateTime.Parse((string)instancia.Element(ra + "dt_created")); 
tabla.dt_updated = DateTime.Parse((string)instancia.Element(ra + "dt_updated")); 
tabla.id_original_clone = (int)instancia.Element(ra + "id_original_clone"); 
tabla.target_locs = (int)instancia.Element(ra + "target_locs"); 
tabla.id_poll = (int)instancia.Element(ra + "id_poll"); 

此代码现在给第三行的异常! (以tabla.Poll_Instance_id开头的那个)。如果我在最后一行之前的“错误”代码上设置了一个断点,我可以检查VS是否确实正在从XML中检索值,并按照预期在对象tabla上进行设置;所以我不知道发生了什么事。

+0

所以你说你改变最后一行,然后编码几行,然后停止工作?这没有任何意义,必须有别的事情发生。 – svick

+1

可能发生的唯一方法是如果您在缺少值的相同代码上使用不同的XML。它不会像你声称的那样神奇地随机失败。 –

+0

@svick你说得对,那没有任何意义。测试之间唯一改变的是最后一行,然后代码在之前破解了几行。 –

回答

0

我已经找到了解决方案,这要归功于@lazyberezovsky指着我的权利方向与根()的东西。

问题出在Descendants()方法,它给我所有的后代节点;所以我得到了PollInstance节点以及Poll_instance_id和其他。这就是为什么它在“正确”代码的第一行中断:在处理第一个节点之后,它在其他节点上窒息。

相反,我必须使用Elements()方法,它只返回直接的孩子;在我的情况下,只有PollInstance

1

您的日期字符串格式无效a.m. - 使用am无点

<?xml version="1.0" encoding="utf-8"?> 
<root xmlns="http://daniel.ponticelli.com/ns/dataExport"> 
    <PollInstance> 
    <Poll_Instance_id>1</Poll_Instance_id> 
    <POLL_description>Mes 1</POLL_description> 
    <dt_start>01/09/2012 12:00:00 am</dt_start> 
    <dt_end>30/09/2012 12:00:00 am</dt_end> 
    <POLL_status>0</POLL_status> 
    <dt_created>03/09/2012 09:50:36 am</dt_created> 
    <dt_updated>03/09/2012 09:50:36 am</dt_updated> 
    <id_original_clone>0</id_original_clone> 
    <target_locs>0</target_locs> 
    <id_poll>1</id_poll> 
    </PollInstance> 
</root> 

也越来越instancia节点时,你应该使用的命名空间,还是应该从根xdoc.Root.Descendants().First()开始:

XNamespace ra = "http://daniel.ponticelli.com/ns/dataExport"; 
XElement instancia = xdoc.Descendants(ra + "PollInstance").First(); 

tabla.Poll_Instance_id = (int)instancia.Element(ra + "Poll_Instance_id"); 
tabla.POLL_description = (string)instancia.Element(ra + "POLL_description"); 
tabla.dt_start = ParseDate((string)instancia.Element(ra + "dt_start")); 
tabla.dt_end = ParseDate((string)instancia.Element(ra + "dt_end")); 
tabla.POLL_status = (int)instancia.Element(ra + "POLL_status"); 
tabla.dt_created = ParseDate((string)instancia.Element(ra + "dt_created")); 
tabla.dt_updated = ParseDate((string)instancia.Element(ra + "dt_updated")); 
tabla.id_original_clone = (int)instancia.Element(ra + "id_original_clone"); 
tabla.target_locs = (int)instancia.Element(ra + "target_locs"); 
tabla.id_poll = (int)instancia.Element(ra + "id_poll"); 

而且使用ParseExact以您的格式解析日期

static DateTime ParseDate(string s) 
{ 
    return DateTime.ParseExact(s, "dd/MM/yyyy hh:mm:ss tt", 
           CultureInfo.InvariantCulture); 
} 

更新,如果你不能改变你的XML数据的格式,然后简单地做String.Replace改变a.m.am

static DateTime ParseDate(string s) 
{ 
    string dateString = s.Replace("a.m.", "AM").Replace("p.m.", "PM"); 
    return DateTime.ParseExact(dateString, 
      "dd/MM/yyyy hh:mm:ss tt", CultureInfo.InvariantCulture); 
} 
+1

而不是编辑XML以将所有'am'改为'am',使用字符串'Replace(“。”,“”)'方法之后的值将它们从XML中提取出来,然后将它们转换为'DateTime.' –

+0

@ChuckSavage同意,这也是解决方案。取决于谁在创建这些XML。如果OP,那么我认为最好更改写入xml的数据格式。如果他只是读取,比是的,字符串替换会做这项工作 –

+0

@lazyberezovsky日期正在解析好了。即使评论加载日期的行,问题仍然存在。我会尝试一下你在命名空间和根节点上所说的话。 –