【问题标题】:XmlReader skipping some blocksXmlReader 跳过一些块
【发布时间】:2012-07-19 09:53:23
【问题描述】:

我的 xml 结构如下:

Header
  \-Timeseries (1-N)
        \- Period (1-N)
              \- Interval (1-N)

这是一个大概的例子:

<Header>
<Element />
    <Timeseries>
       <Element />
       <Period>
           <Element />
           <Interval>
               <Element />
           </Interval>
       </Period>
    </Timeseries>
</Header>

我希望读取标题元素,直到我点击 Timeseries,然后是 Timeseries 元素,直到我点击 Period,然后是 Period,直到我点击 Interval,和 Interval,直到我点击 Interval 的末尾。当我完成一个句号时,我正在写所有的间隔。

此特定文档有 614 个时间序列,每个时间序列有 1 个周期。

我正在解析它:

while (!xmlReader.EOF)
{
    if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "Header")
    {
        while (xmlReader.Name != "Timeseries" && xmlReader.Read())
        {
            // read
        }
    }
    else if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "Timeseries")
    {
        while (xmlReader.Name != "Period" && xmlReader.Read())
        {
            // read
        }           
    }
    else if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "Period")
    {
        while (xmlReader.Name != "Interval" && xmlReader.Read())
        {
            // read
        }
    }
    else if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "Interval")
    {
        while (xmlReader.NodeType != XmlNodeType.EndElement && xmlReader.Read())
        {
            // read
        }
    }
    else if (xmlReader.NodeType == XmlNodeType.EndElement && xmlReader.Name == "Period")
    {
        // write intervals
    }
    else
    {
        xmlReader.Read();
    }
}

似乎只读取了 166/614 个句点。因此,我一定是在吞噬一些 xml,但在发现错误时遇到了麻烦。

转储读取表明时间序列 1-166 已正确解析,但此后不知何故解析停止。

【问题讨论】:

  • 愚蠢的问题,但使用XDocument和一些LINQ不会更容易吗?
  • @TiesonT。很不幸的是,不行。有问题的文档可能非常大(最大 1GB),解析速度很重要。

标签: c# .net xmlreader code-inspection


【解决方案1】:

不确定它是否有帮助,但如果速度是一个问题,也许这会稍微快一点?

while (!xmlReader.EOF)
{
    switch(xmlReader.NodeType)
    {
        case XmlNodeType.Element:
            switch(xmlReader.Name)
            {
                case "Header":
                    while (xmlReader.Name != "Timeseries" && xmlReader.Read()) // advance to next node
                    {
                        // read
                    }
                    break;
                case "Timeseries":
                    while (xmlReader.Name != "Period" && xmlReader.Read()) // advance to next node
                    {
                        // read
                    }  
                    break;
                case "Period":
                    while (xmlReader.Name != "Interval" && xmlReader.Read()) // advance to next node
                    {
                        // read
                    }
                    break;
                case "Interval":
                    while (xmlReader.NodeType != XmlNodeType.EndElement && xmlReader.Read()) // advance to next node
                    {
                        // read
                    }
                    break;
            }
            break;

        case XmlNodeType.EndElement:
            if(xmlReader.Name == "Period")
            {
                // write intervals
            }
            break;

        default:
            xmlReader.Read(); // advance to next node
            break;
    }
}

从理论上讲,这会减少一些比较,但这可能是无关紧要的差异。

【讨论】:

  • case 将转换为 if-else for ~ N
  • 是的,我知道 switch 编译与 if-else 相同,但我想知道消除每个 else-if 的两部分条件是否会有所帮助。我想如果我真的记得如何计算圈复杂度,我不会想知道......
【解决方案2】:

那是因为它永远不会到达“else if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "Timeseries")”或第二个“else if (xmlReader.NodeType == XmlNodeType.EndElement && xmlReader.Name == "Period")" 部分代码,因为这些条件已被早期的 if 捕获。

【讨论】:

  • 第一个是原题的错误。第二个我很困惑。为什么?
【解决方案3】:

你这里有类型吗? if 语句是“Timeseries”,而 while 语句是“Period”

else if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "Timeseries")
    {
        while (xmlReader.Name != "Period" && xmlReader.Read())
        {
            // read
        }           
    }

你在下面有另一个块做同样的事情。

【讨论】:

  • 我正在阅读 Timeseries 标题,直到遇到一个句号,这是一个子元素。
【解决方案4】:

显然我在测试中计算错误的总时间序列。原始文档也有 166 个 Timeseries。

【讨论】:

  • @TiesonT。是的。很抱歉耽误了您的时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 2023-04-02
  • 1970-01-01
  • 2019-01-19
  • 2016-08-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多