I've run into a problem with streaming XElements and when there's no whitespace.
Given the following code from MSDN documentation about streaming 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;
}
}
}
}
}
This code fails when the elements have no whitespace between them, because the XElement.ReadFrom method moves the current position past the EndElement node. When there's whitespace, the reader is on a Text node, and the code works fine. But when there's no whitespace, the reader is on the next Element node, and the while(reader.Read()) line moves past the element node and you effectively now are skipping every other node.
The problem was "solved" by skipping the while(reader.Read()) line when the correct element returns, ie, add a label "readnext:" to the first line of the while loop and add "goto readnext;" right after yield return:
// 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;
}
}
}
Note that I tried XmlReaderSettings with IgnoreWhitespace=true on the XmlReader.Create line.
Is there a better way here?
Yes don't use 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();
}
}