2013-01-21 83 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日期正在解析好了。即使評論加載日期的行,問題仍然存在。我會嘗試一下你在命名空間和根節點上所說的話。 –