2014-05-06 296 views
3

我有一個6GB的XML文件,我通過文件使用的XmlReader循環。該文件很大,但我無能爲力。我使用LINQ,但大小不讓我使用XDocument,因爲我得到一個OutOfMemory錯誤。通過XML迭代?

我在整個文件中使用的XmlReader循環,並提取我需要什麼。我包含一個示例XML文件。

從本質上講,這是我做的:

  1. 查找標籤集裝箱。如果找到,則檢索屬性「ID」。
  2. 如果「ID」與LOCAL開始,那麼這就是我會閱讀。
  3. 讀者循環,直到我找到標籤家庭與價值CELL_FD
  4. 被發現時,循環的reader.read(),直到我找到標籤IMPORTANT_VALUE
  5. 一旦發現,讀的IMPORTANT_VALUE值。
  6. 我完成了這個容器,所以繼續循環,直到我找到下一個容器(這是休息的地方)。

這是我如何閱讀文件和查找相關值的簡化版本。

while (myReader.Read()) 
{ 
    if ((myReader.Name == "CONTAINER")) 
    { 
     if (myReader.HasAttributes) 
     { 
      string Attribute = myReader.GetAttribute("id"); 
      if (Attribute.IndexOf("LOCAL_") >= 0) 
      { 
       while (myReader.Read()) 
       { 
        if (myReader.Name == "FAMILY") 
        { 
         myReader.Read();//read value 
         string Family = myReader.Value; 
         if (Family == "CELL_FDD") 
         { 
          while (myReader.Read()) 
          { 
           if ((myReader.Name == "IMPORTANT_VALUE")) 
           { 
            myReader.Read(); 
            string Counter = myReader.Value; 
            Console.WriteLine(Attribute + " (found: " + Counter + ")"); 
            break; 
           } 
          } 
         } 
        } 
       } 
      } 
     } 
    } 
} 

而這正是XML:

<es:esFD xmlns:es="File.xsd"> 
    <vs:vsFD xmlns:vs="OTHER_FILE.xsd"> 
    <CONTAINER id="LOCAL_CONTAINER1"> 
     <ATTRIBUTES> 
      <FAMILY>CELL_FDD</FAMILY> 
      <CELL_FDD> 
       <VAL1>1.1.2.3</VAL1> 
       <VAL2>JSMITH</VAL2> 
       <VAL3>320</VAL3> 
       <IMPORTANT_VALUE>VERY</IMPORTANT_VALUE> 
       <VAL4>320</VAL4> 
      </CELL_FDD> 
      <FAMILY>BLAH</FAMILY> 
      <BLAH> 
       <VAL1>1.4.43.3</VAL1> 
       <VAL2>NA</VAL2> 
       <VAL3>349</VAL3> 
       <IMPORTANT_VALUE>NA</IMPORTANT_VALUE> 
       <VAL4>43</VAL4> 
       <VAL5>00</VAL5> 
       <VAL6>12</VAL6> 
      </BLAH> 
     </ATTRIBUTES> 
    </CONTAINER>  
    <CONTAINER id="FOREIGN_ELEMENT1"> 
     <ATTRIBUTES> 
      <FAMILY>CELL_FDD</FAMILY> 
      <CELL_FDD> 
       <VAL1>1.1.2.3</VAL1> 
       <VAL2>JSMITH</VAL2> 
       <VAL3>320</VAL3> 
       <IMPORTANT_VALUE>VERY</IMPORTANT_VALUE> 
       <VAL4>320</VAL4> 
      </CELL_FDD> 
      <FAMILY>BLAH</FAMILY> 
      <BLAH> 
       <VAL1>1.4.43.3</VAL1> 
       <VAL2>NA</VAL2> 
       <VAL3>349</VAL3> 
       <IMPORTANT_VALUE>NA</IMPORTANT_VALUE> 
       <VAL4>43</VAL4> 
       <VAL5>00</VAL5> 
       <VAL6>12</VAL6> 
      </BLAH> 
     </ATTRIBUTES> 
    </CONTAINER>  
    </vs:vsFD> 
</es:esFD> 

如何從最內環打破這樣我就可以達到最頂端的循環?

+1

而問題是什麼? – MarcinJuraszek

+0

您是否希望'break'將您返回到正在查找CONTAINER元素的循環? –

+0

我編輯了這個問題,但是,我想打破最上面的循環。或者繼續閱讀下一個CONTAINER,因爲我不會讀取當前CONTAINER中的任何其他內容。 – vmgmail

回答

-1

使用svick的評論,我結束了LINQ結合到XML。一旦我到達正確的元素,並檢查該屬性是否具有正確的ID,我將它轉儲到XElement.Load。

+0

考慮添加一些代碼來說明您的觀點,並嘗試更好地解釋您的答案。這樣,它可以幫助那些和你有類似問題的未來讀者。 – Kendra

4

使用不同的方法應該更容易控制你的循環:

while (myReader.Read()) 
{ 
    if ((myReader.Name == "CONTAINER")) 
    { 
     ProcessContainerElement(myReader); 
    } 
} 

ProcessContainerElement方法,你可以return,當你確定你需要開始尋找下一個容器元素。

private void ProcessContainerElement(XmlReader myReader) 
{ 
    while (whatever) 
    { 
     if ((myReader.Name == "IMPORTANT_VALUE")) 
     { 
      myReader.Read(); 
      string Counter = myReader.Value; 
      Console.WriteLine(Attribute + " (found: " + Counter + ")"); 
      return; 
     } 
    } 
} 
1

您可以使用XmlReader和每個節點讀取到XmlDocument。

這樣的事情,沒有測試:

bool notFound = false; 
notFound |= !reader.ReadToDescendant("root"); 
notFound |= !reader.ReadToDescendant("CONTAINER"); 

if (notFound) 
    Throw new Exception("[Не удаётся найти \"/root/CONTAINER\"]"); 

do 
{ 
    XmlDocument doc = new XmlDocument(); 
    doc.LoadXml(reader.ReadOuterXml()); 
    XmlNode container = doc.DocumentElement; 

    // do your work with container 
} 
while (reader.ReadToNextSibling("CONTAINER")); 

reader.Close();