我有一个6GB的XML文件,我正在使用XmlReader循环遍历该文件。文件很大但我无能为力。我使用LINQ,但是大小不允许我使用XDocument,因为我得到一个OutOfMemory错误。
我正在使用XmlReader遍历整个文件并提取我需要的内容。我正在包含一个示例XML文件。
基本上,这就是我所做的:
这是我阅读文件和查找相关值的简化版本。
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>
如何摆脱最内圈,以便能够达到最顶层的循环?
答案 0 :(得分:4)
使用单独的方法可以更容易地控制循环:
while (myReader.Read())
{
if ((myReader.Name == "CONTAINER"))
{
ProcessContainerElement(myReader);
}
}
在ProcessContainerElement
方法中,当您确定需要开始寻找下一个CONTAINER元素时,可以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 :(得分: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();
答案 2 :(得分:-1)
使用 svick 的评论,我最终将LINQ与XML结合起来。一旦我到达了正确的元素并检查该属性是否具有正确的ID,我将其转储到XElement.Load。