2010-02-12 48 views
1

我正在處理通常非常好的開源項目Excel Data Reader中的一個神祕錯誤。它跳過了從我的特定OpenXML .xlsx電子表格中讀取的值。使用ReadToDescendant和/或ReadElementContentAsObject更正XmlReader問題

問題發生在ReadSheetRow method(演示代碼如下)。源XML由Excel保存並且不包含發生奇怪行爲時的空白。但是,使用空格重新格式化的XML(例如在Visual Studio中轉到編輯,高級,格式化文檔)工作得很好!

與空白測試數據:無空白

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"> 
    <sheetData> 
     <row r="5" spans="1:73" s="7" customFormat="1"> 
      <c r="B5" s="12"> 
       <v>39844</v> 
      </c> 
      <c r="C5" s="8"/> 
      <c r="D5" s="8"/> 
      <c r="E5" s="8"/> 
      <c r="F5" s="8"/> 
      <c r="G5" s="8"/> 
      <c r="H5" s="12"> 
       <v>39872</v> 
      </c> 
      <c r="I5" s="8"/> 
      <c r="J5" s="8"/> 
      <c r="K5" s="8"/> 
      <c r="L5" s="8"/> 
      <c r="M5" s="8"/> 
      <c r="N5" s="12"> 
       <v>39903</v> 
      </c> 
     </row> 
    </sheetData> 
</worksheet> 

測試數據:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"><sheetData><row r="5" spans="1:73" s="7" customFormat="1"><c r="B5" s="12"><v>39844</v></c><c r="C5" s="8"/><c r="D5" s="8"/><c r="E5" s="8"/><c r="F5" s="8"/><c r="G5" s="8"/><c r="H5" s="12"><v>39872</v></c><c r="I5" s="8"/><c r="J5" s="8"/><c r="K5" s="8"/><c r="L5" s="8"/><c r="M5" s="8"/><c r="N5" s="12"><v>39903</v></c></row></sheetData></worksheet> 

實施例代碼演示該問題:

注意在_xmlReader.Read(),BReadToDescendant,C 後輸出10A

while (reader.Read()) 
{ 
    if (reader.NodeType != XmlNodeType.Whitespace) outStream.WriteLine(String.Format("*A* NodeType: {0}, Name: '{1}', Empty: {2}, Value: '{3}'", reader.NodeType, reader.Name, reader.IsEmptyElement, reader.Value)); 

    if (reader.NodeType == XmlNodeType.Element && reader.Name == "c") 
    { 
     string a_s = reader.GetAttribute("s"); 
     string a_t = reader.GetAttribute("t"); 
     string a_r = reader.GetAttribute("r"); 

     bool matchingDescendantFound = reader.ReadToDescendant("v"); 
     if (reader.NodeType != XmlNodeType.Whitespace) outStream.WriteLine(String.Format("*B* NodeType: {0}, Name: '{1}', Empty: {2}, Value: '{3}'", reader.NodeType, reader.Name, reader.IsEmptyElement, reader.Value)); 
     object o = reader.ReadElementContentAsObject(); 
     if (reader.NodeType != XmlNodeType.Whitespace) outStream.WriteLine(String.Format("*C* NodeType: {0}, Name: '{1}', Empty: {2}, Value: '{3}'", reader.NodeType, reader.Name, reader.IsEmptyElement, reader.Value)); 
    } 
} 

爲XML測試結果與空白:

 
*A* NodeType: XmlDeclaration, Name: 'xml', Empty: False, Value: 'version="1.0" encoding="UTF-8" standalone="yes"' 
*A* NodeType: Element, Name: 'worksheet', Empty: False, Value: '' 
*A* NodeType: Element, Name: 'sheetData', Empty: False, Value: '' 
*A* NodeType: Element, Name: 'row', Empty: False, Value: '' 
*A* NodeType: Element, Name: 'c', Empty: False, Value: '' 
*B* NodeType: Element, Name: 'v', Empty: False, Value: '' 
*A* NodeType: EndElement, Name: 'c', Empty: False, Value: '' 
*A* NodeType: Element, Name: 'c', Empty: True, Value: '' 
*B* NodeType: Element, Name: 'c', Empty: True, Value: '' 
... 

測試結果爲XML無空白:

 
*A* NodeType: XmlDeclaration, Name: 'xml', Empty: False, Value: 'version="1.0" encoding="UTF-8" standalone="yes"' 
*A* NodeType: Element, Name: 'worksheet', Empty: False, Value: '' 
*A* NodeType: Element, Name: 'sheetData', Empty: False, Value: '' 
*A* NodeType: Element, Name: 'row', Empty: False, Value: '' 
*A* NodeType: Element, Name: 'c', Empty: False, Value: '' 
*B* NodeType: Element, Name: 'v', Empty: False, Value: '' 
*C* NodeType: EndElement, Name: 'c', Empty: False, Value: '' 
*A* NodeType: Element, Name: 'c', Empty: True, Value: '' 
*B* NodeType: Element, Name: 'c', Empty: True, Value: '' 
... 

格局的變化表明ReadElementContentAsObject或者可能是一個問題ReadToDescendant將XmlReader移動到的位置。

有誰知道這裏可能會發生什麼?

+0

那麼,你有沒有回顧過Excel Data Reader的來源?你似乎暗示問題在於...... – 2010-02-12 08:47:28

+0

@silky:是的,我的演示代碼是相同的邏輯。要麼代碼沒有正確使用XmlReader,要麼在XmlReader中存在錯誤。前者很可能,但我看不出有什麼不對。 – 2010-02-12 10:11:17

回答

1

這很簡單。從輸出中可以看到,第一次使用「B」這一行時,您將位於第一個'v'元素。然後,您調用ReadElementContentAsObject。返回v,的文本內容「將閱讀器移動到末端元素標記」。 (v)。如果存在空格,則您現在指向空白節點,或者如果沒有,則指向(c)的EndElement節點。當然,如果輸出是空格,則不會輸出。無論哪種方式,您然後執行Read()並繼續下一個元素。在非空白的情況下,你已經失去了EndElement。

這個問題在其他情況下更糟糕。當你做一個c的ReadElementContentAsObject(稱之爲c1),然後繼續下一個c(c2)。然後你做一個閱讀,移動到c3,並失去c2。我不打算修復real code。但很明顯,你需要擔心的是,將流向不止一個地方推進。這是一般循環錯誤的常見來源。