通过XML进行迭代

本文关键字:迭代 XML 通过 | 更新日期: 2023-09-27 18:02:14

我有一个6GB的XML文件,我使用XmlReader来遍历该文件。文件很大,但我对此无能为力。我使用LINQ,但大小不让我使用XDocument,因为我得到一个OutOfMemory错误。

我使用XmlReader遍历整个文件并提取我需要的内容。我将包括一个示例XML文件。

基本上,这就是我所做的:

  1. 查找标签容器。如果找到,则检索属性"ID"。
  2. 如果"ID"以LOCAL开头,那么这就是我将阅读的内容。
  3. 阅读器循环,直到我找到标签FamilyCELL_FD
  4. 找到后,循环reader.read(),直到找到tag IMPORTANT_VALUE
  5. 找到后读取IMPORTANT_VALUE的值。
  6. 我已经完成了这个容器,所以继续循环,直到我找到下一个容器(这就是break进来的地方)。

这是我如何读取文件并找到相关值的简化版本。

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>

我怎样才能从最里面的循环跳出来,到达最上面的循环呢?

通过XML进行迭代

使用单独的方法可以更容易地控制循环:

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;
        }
    }
}

您可以使用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();

使用svick的注释,我最终将LINQ与XML结合起来。在找到正确的元素并检查属性具有正确的ID之后,我将其转储到XElement.Load.