没有空格时流式传输 XElements 异常

streaming XElements oddity when there's no whitespace

我 运行 遇到流式 XElements 和没有空格的问题。

鉴于 MSDN 文档中有关流式传输 XElements 的以下代码,

    public static IEnumerable<XElement> StreamElements(Stream source, string elementName)
    {
        using (XmlReader reader = XmlReader.Create(source))
        {
            XElement item = null;

            reader.MoveToContent();

            // Parse the file, save header information when encountered, and yield the
            // Item XElement objects as they are created.

            // loop through codeFile elements
            while (reader.Read())
            {
                if (reader.NodeType == XmlNodeType.Element && reader.Name == elementName)
                {
                    item = XElement.ReadFrom(reader) as XElement;

                    if (item != null) 
                    {
                        yield return item;
                    }
                }
            }
        }
    }

当元素之间没有空格时,此代码失败,因为 XElement.ReadFrom 方法将当前位置移动到 EndElement 节点之后。当有空格时,reader 在 Text 节点上,代码工作正常。但是当没有空格时,reader 位于下一个 Element 节点上,而 while(reader.Read()) 行移过元素节点,您现在实际上正在跳过所有其他节点。

问题是 "solved" 通过在正确的元素 return 时跳过 while(reader.Read()) 行,即添加标签 "readnext:" while 循环的第一行并在 yield return:

之后添加 "goto readnext;"
            // loop through codeFile elements
            while (reader.Read())
            {
                readnext:
                if (reader.NodeType == XmlNodeType.Element && reader.Name == elementName)
                {

                    item = XElement.ReadFrom(reader) as XElement;

                    if (item != null) 
                    {
                        yield return item;
                        goto readnext;
                    }
                }
            }

请注意,我在 XmlReader.Create 行中尝试使用 XmlReaderSettings 和 IgnoreWhitespace=true。

这里有更好的方法吗?

是的,不要使用 goto

reader.Read();
while (!reader.EOF)
{
    if (reader.NodeType == XmlNodeType.Element && reader.Name == elementName)
    {
        item = XElement.ReadFrom(reader) as XElement;

        if (item != null) 
        {
            yield return item;
        }
    }
    else
    {
        reader.Read();
    }
}