2010-02-12 4 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> 

예제 코드 :

주을 그 10 A은 ReadToDescendant 이후에 _xmlReader.Read(), B및 다음에 ReadElementContentAsObject 다음에 출력됩니다. 공백을 XML에 대한

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: '' 
... 

테스트 결과 :

 
*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 데이터 판독기의 원본을 검토해 보셨습니까? 당신은 그 안에 문제가 있다는 것을 암시하는 것처럼 보입니다 ... –

+0

@ 실 키스 : 예, 내 데모 코드는 같은 논리입니다.코드에서 XmlReader를 올바르게 사용하지 않거나 XmlReader에 버그가 있습니다. 전직 가능성은 매우 높지만 무엇이 잘못되었는지는 알 수 없습니다. –

답변

1

상당히 간단합니다. 출력에서 볼 수 있듯이 처음으로 "B"행을 사용하면 첫 번째 'v'요소에 배치됩니다. 그런 다음 ReadElementContentAsObject를 호출합니다. 그러면 v의 텍스트 내용이 "최종 요소 태그를 지나쳐 리더를 이동합니다." (of of). 공백이 있으면 공백 노드를 가리키고 그렇지 않으면 c의 EndElement 노드를 가리 킵니다. 물론 공백 인 경우 출력물이 출력되지 않습니다. 어느 쪽이든, 당신은 다음 Read()를하고 다음 요소로 이동합니다. 공백이 아닌 경우 EndElement를 잃어 버렸습니다.

다른 위치에서는 문제가 훨씬 심각합니다. c의 ReadElementContentAsObject (c1)를 호출하면 다음 c (c2)로 이동합니다. 그렇다면 당신은 읽기를하고, c3으로 이동하고, c2를 잃어 버립니다.

나는 real code을 고치려고하지 않을 것입니다. 그러나 당신이 걱정해야 할 것은 분명합니다. 하나 이상의 장소에서 시내를 앞으로 움직이십시오. 이것은 일반적으로 루핑 오류의 공통 소스입니다.