using System.Collections.Generic;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO.Compression;
using System.Text.RegularExpressions;
public static partial class XmlReaderExtensions
public static IEnumerable<XmlReader> ReadElements(this XmlReader inReader, string localName, string namespaceURI)
inReader.MoveToContent();
if (inReader.NodeType != XmlNodeType.Element)
throw new InvalidOperationException("The reader is not positioned on an element.");
var isEmpty = inReader.IsEmptyElement;
switch (inReader.NodeType)
case XmlNodeType.EndElement:
case XmlNodeType.Element:
if (inReader.LocalName == localName && inReader.NamespaceURI == namespaceURI)
using (var subReader = inReader.ReadSubtree())
subReader.MoveToContent();
public static IEnumerable<XmlReader> ReadDescendants(this XmlReader inReader, string localName, string namespaceURI)
inReader.MoveToContent();
if (inReader.NodeType != XmlNodeType.Element)
throw new InvalidOperationException("The reader is not positioned on an element.");
using (var reader = inReader.ReadSubtree())
while (reader.ReadToFollowing(localName, namespaceURI))
using (var subReader = inReader.ReadSubtree())
subReader.MoveToContent();
public static void Test()
foreach (var xml in GetNestedXml())
const string fullFileName = "Question58692275.zip";
static void Test(string inXml)
foreach (var xml in new[] { inXml, XDocument.Parse(inXml).ToString(SaveOptions.DisableFormatting), XDocument.Parse(inXml).ToString(SaveOptions.None) })
File.Delete(fullFileName);
using (var archive = ZipFile.Open(fullFileName, ZipArchiveMode.Create))
var xmlFile = archive.CreateEntry("widgets1.xml");
using (var entryStream = xmlFile.Open())
using (var streamWriter = new StreamWriter(entryStream))
TestNestedReadElements(xml);
TestNestedDescendants(xml);
private static void TestNestedReadElements(string xml)
var zipListBox = new List<string>();
using (var archive = ZipFile.Open(fullFileName, ZipArchiveMode.Read))
foreach (var entry in archive.Entries)
if (Path.GetExtension(entry.Name).Equals(".xml", StringComparison.OrdinalIgnoreCase))
using (var zipEntryStream = entry.Open())
using (var reader = XmlReader.Create(zipEntryStream))
.ReadElements("Widgets", "")
.SelectMany(r => r.ReadElements("Widget", ""))
.SelectMany(r => r.ReadElements("Description", "").Select(i => i.ReadElementContentAsString()).Take(1));
zipListBox.AddRange(query);
Assert.IsTrue(Regex.Matches(xml, "My Description").Count == zipListBox.Count);
using (var archive = ZipFile.Open(fullFileName, ZipArchiveMode.Read))
foreach (var entry in archive.Entries)
if (Path.GetExtension(entry.Name).Equals(".xml", StringComparison.OrdinalIgnoreCase))
using (var zipEntryStream = entry.Open())
using (var reader = XmlReader.Create(zipEntryStream))
.ReadElements("Widgets", "")
.SelectMany(r => r.ReadElements("Widget", ""))
.Select(r => XElement.Load(r))
.Select(e => new { Description = e.Element("Description")?.Value, Id = e.Attribute("id")?.Value, Name = e.Element("Name")?.Value });
foreach (var widget in query)
Console.WriteLine("Id = {0}, Name = {1}, Description = {2}", widget.Id, widget.Name, widget.Description);
private static void TestNestedDescendants(string xml)
var zipListBox = new List<string>();
using (var archive = ZipFile.Open(fullFileName, ZipArchiveMode.Read))
foreach (var entry in archive.Entries)
if (Path.GetExtension(entry.Name).Equals(".xml", StringComparison.OrdinalIgnoreCase))
using (var zipEntryStream = entry.Open())
using (var reader = XmlReader.Create(zipEntryStream))
.ReadDescendants("Widget", "")
.SelectMany(r => r.ReadElements("Description", "").Select(i => i.ReadElementContentAsString()).Take(1));
zipListBox.AddRange(query);
Assert.IsTrue(Regex.Matches(xml, "My Description").Count == zipListBox.Count);
using (var archive = ZipFile.Open(fullFileName, ZipArchiveMode.Read))
foreach (var entry in archive.Entries)
if (Path.GetExtension(entry.Name).Equals(".xml", StringComparison.OrdinalIgnoreCase))
using (var zipEntryStream = entry.Open())
using (var reader = XmlReader.Create(zipEntryStream))
.ReadDescendants("Widget", "")
.Select(r => XElement.Load(r))
.Select(e => new { Description = e.Element("Description")?.Value, Id = e.Attribute("id")?.Value, Name = e.Element("Name")?.Value });
foreach (var widget in query)
Console.WriteLine("Id = {0}, Name = {1}, Description = {2}", widget.Id, widget.Name, widget.Description);
static IEnumerable<string> GetNestedXml()
return GetXml().Select(s => "<Document>" + s + "</Document>");
static IEnumerable<string> GetXml()
@"<Widgets><Widget /></Widgets>",
<Widget id=""0""><!--Comment-->
<Description>My Description</Description>
<Bar><Foo>Description</Foo></Bar>
<Widget id=""2""><Description>My Description</Description><Bar><Foo>Description</Foo></Bar>
<NotAWidget id=""x""/><Widget id=""0""><Description>My Description</Description><Bar><Foo>Description</Foo></Bar></Widget><Widget id=""1""/><Widget id=""2""><Description>My Description</Description><Bar><Foo>Description</Foo></Bar></Widget><NotAWidget id=""x""></NotAWidget><NotAWidget id=""x""/>
<Widget id=""0""><!--Comment-->
<Description>My Description</Description>
<Bar><Foo>Description</Foo></Bar>
<Widget id=""2""><Description>My Description</Description><Bar><Foo>Description</Foo></Bar>
<NotAWidget id=""x""/><Widget id=""0""><Description>My Description</Description><Bar><Foo>Description</Foo></Bar></Widget><Widget id=""1""/><Widget id=""2""><Description>My Description</Description><Bar><Foo>Description</Foo></Bar></Widget><NotAWidget id=""x""></NotAWidget><NotAWidget id=""x""/><Widget id=""0""><!--Comment-->
<Description>My Description</Description>
<Bar><Foo>Description</Foo></Bar>
</Widget><Widget id=""1""/>
<Widget id=""2""><Description>My Description</Description><Bar><Foo>Description</Foo></Bar>
</NotAWidget><NotAWidget id=""x""/><Widget id=""0""><Description>My Description</Description><Bar><Foo>Description</Foo></Bar></Widget><Widget id=""1""/><Widget id=""2""><Description>My Description</Description><Bar><Foo>Description</Foo></Bar></Widget><NotAWidget id=""x""></NotAWidget><NotAWidget id=""x""/>
public static void Main()
Console.WriteLine("Environment version: {0} ({1})", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , GetNetCoreVersion());
Console.WriteLine("Failed with unhandled exception: ");
public static string GetNetCoreVersion()
var assembly = typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly;
var assemblyPath = assembly.CodeBase.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
if (netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2)
return assemblyPath[netCoreAppIndex + 1];