From 1ee856639eb6487a80db8dc60e8389257a4f5f93 Mon Sep 17 00:00:00 2001 From: Vladimir Pecanac Date: Sun, 1 Nov 2026 13:23:01 +0100 Subject: [PATCH] Read XML: net10.0, MSTest 4.5.2, read people.xml from file Retarget ReadXML and Tests to net10.0 and move the test packages to Microsoft.NET.Test.Sdk 18.11.0, MSTest 4.5.2 and coverlet.collector 10.1.0 (Assert.ThrowsException becomes Assert.ThrowsExactly). Add people.xml with a copy-to-output item, ReadXmlFromFile (XDocument.Load and XmlReader.Create) and ReadXmlUsingXmlDocument, with four tests. Rename ReadNamesAndAges to ReadNamesAndSurnames and drop the stray block after the using declaration. Program.cs gains the file-reading demos. --- xml-csharp/ReadXML/ReadXML/Program.cs | 28 +++++++++-- .../ReadXML/ReadXML/Read/ReadXmlFromFile.cs | 35 ++++++++++++++ .../ReadXML/Read/ReadXmlUsingXmlDocument.cs | 18 ++++++++ .../ReadXML/Read/ReadXmlUsingXmlReader.cs | 45 +++++++++--------- xml-csharp/ReadXML/ReadXML/ReadXML.csproj | 6 ++- xml-csharp/ReadXML/ReadXML/people.xml | 35 ++++++++++++++ .../Tests/Read/ReadXmlFromFileTests.cs | 46 +++++++++++++++++++ .../Tests/Read/ReadXmlUsingXmlReaderTest.cs | 4 +- xml-csharp/ReadXML/Tests/Tests.csproj | 10 ++-- 9 files changed, 193 insertions(+), 34 deletions(-) create mode 100644 xml-csharp/ReadXML/ReadXML/Read/ReadXmlFromFile.cs create mode 100644 xml-csharp/ReadXML/ReadXML/Read/ReadXmlUsingXmlDocument.cs create mode 100644 xml-csharp/ReadXML/ReadXML/people.xml create mode 100644 xml-csharp/ReadXML/Tests/Read/ReadXmlFromFileTests.cs diff --git a/xml-csharp/ReadXML/ReadXML/Program.cs b/xml-csharp/ReadXML/ReadXML/Program.cs index d89ffb588b..9d706d92c2 100644 --- a/xml-csharp/ReadXML/ReadXML/Program.cs +++ b/xml-csharp/ReadXML/ReadXML/Program.cs @@ -51,11 +51,33 @@ Console.ReadKey(); Console.Clear(); -Console.WriteLine("XmlReader: Read names and ages from XML document with people data:\n"); +Console.WriteLine("XmlReader: Read names and surnames from XML document with people data:\n"); Console.WriteLine("\n---\n"); -ReadXmlUsingXmlReader.ReadNamesAndAges( +ReadXmlUsingXmlReader.ReadNamesAndSurnames( CreateXmlUsingXmlWriter.CreateAnArrayOfPeople(people) ) .ToList() .ForEach(Console.WriteLine); -Console.ReadKey(); \ No newline at end of file +Console.ReadKey(); + +Console.Clear(); +Console.WriteLine("Read an XML file from the output folder:\n"); +Console.WriteLine("\n---\n"); +ReadXmlFromFile.ReadEmailsUsingXDocument(ReadXmlFromFile.FilePath) + .ToList() + .ForEach(Console.WriteLine); +ReadXmlFromFile.ReadEmailsUsingXmlReader(ReadXmlFromFile.FilePath) + .ToList() + .ForEach(Console.WriteLine); +ReadXmlUsingXmlDocument.ReadEmails(ReadXmlFromFile.FilePath) + .ToList() + .ForEach(Console.WriteLine); +Console.ReadKey(); + +Console.Clear(); +Console.WriteLine("XmlReader: Read names and surnames from people.xml:\n"); +Console.WriteLine("\n---\n"); +var xml = File.ReadAllText(ReadXmlFromFile.FilePath); + +foreach (var row in ReadXmlUsingXmlReader.ReadNamesAndSurnames(xml)) + Console.WriteLine(row); diff --git a/xml-csharp/ReadXML/ReadXML/Read/ReadXmlFromFile.cs b/xml-csharp/ReadXML/ReadXML/Read/ReadXmlFromFile.cs new file mode 100644 index 0000000000..61686d29c4 --- /dev/null +++ b/xml-csharp/ReadXML/ReadXML/Read/ReadXmlFromFile.cs @@ -0,0 +1,35 @@ +using System.Xml; +using System.Xml.Linq; + +namespace ReadXml.Read +{ + public static class ReadXmlFromFile + { + public static readonly string FilePath = + Path.Combine(AppContext.BaseDirectory, "people.xml"); + + public static IEnumerable ReadEmailsUsingXDocument(string path) + { + var xmlDoc = XDocument.Load(path); + + return xmlDoc.Root! + .Elements("person") + .Select(person => person.Element("email")!.Value) + .ToList(); + } + + public static IEnumerable ReadEmailsUsingXmlReader(string path) + { + using var reader = XmlReader.Create(path); + + List result = []; + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element && reader.Name == "email") + result.Add(reader.ReadElementContentAsString()); + } + + return result; + } + } +} diff --git a/xml-csharp/ReadXML/ReadXML/Read/ReadXmlUsingXmlDocument.cs b/xml-csharp/ReadXML/ReadXML/Read/ReadXmlUsingXmlDocument.cs new file mode 100644 index 0000000000..8d4a326734 --- /dev/null +++ b/xml-csharp/ReadXML/ReadXML/Read/ReadXmlUsingXmlDocument.cs @@ -0,0 +1,18 @@ +using System.Xml; + +namespace ReadXml.Read +{ + public static class ReadXmlUsingXmlDocument + { + public static IEnumerable ReadEmails(string path) + { + var xmlDoc = new XmlDocument(); + xmlDoc.Load(path); + + return xmlDoc.GetElementsByTagName("email") + .Cast() + .Select(node => node.InnerText) + .ToList(); + } + } +} diff --git a/xml-csharp/ReadXML/ReadXML/Read/ReadXmlUsingXmlReader.cs b/xml-csharp/ReadXML/ReadXML/Read/ReadXmlUsingXmlReader.cs index 7275cb9ab5..dd7b26df46 100644 --- a/xml-csharp/ReadXML/ReadXML/Read/ReadXmlUsingXmlReader.cs +++ b/xml-csharp/ReadXML/ReadXML/Read/ReadXmlUsingXmlReader.cs @@ -33,39 +33,38 @@ public static IEnumerable ReadXmlWithoutWhiteSpace(string xml) return result; } - public static IEnumerable ReadNamesAndAges(string xml) + public static IEnumerable ReadNamesAndSurnames(string xml) { var settings = new XmlReaderSettings { IgnoreWhitespace = true }; - List result = []; using var reader = XmlReader.Create(new StringReader(xml), settings); + + List result = []; + var personData = new PersonData(); + var numberOfPersons = 0; + + while (reader.Read()) { - var personData = new PersonData(); - var numberOfPersons = 0; + if (reader.NodeType == XmlNodeType.Element) + { + if (reader.Name == "person") + personData.Init(); + + if (reader.Name == "firstName") + personData.FirstName = reader.ReadElementContentAsString(); + + if (reader.Name == "lastName") + personData.LastName = reader.ReadElementContentAsString(); + } - while (reader.Read()) + if (reader.NodeType == XmlNodeType.EndElement) { - if (reader.NodeType == XmlNodeType.Element) - { - if (reader.Name == "person") - personData.Init(); - - if (reader.Name == "firstName") - personData.FirstName = reader.ReadElementContentAsString(); - - if (reader.Name == "lastName") - personData.LastName = reader.ReadElementContentAsString(); - } - - if (reader.NodeType == XmlNodeType.EndElement) - { - if (reader.Name == "person") - result.Add($"#{++numberOfPersons,3} | " + - $"{personData.FirstName,-15} | {personData.LastName,-15}"); - } + if (reader.Name == "person") + result.Add($"#{++numberOfPersons,3} | " + + $"{personData.FirstName,-15} | {personData.LastName,-15}"); } } diff --git a/xml-csharp/ReadXML/ReadXML/ReadXML.csproj b/xml-csharp/ReadXML/ReadXML/ReadXML.csproj index 206b89a9a8..0f010a94d1 100644 --- a/xml-csharp/ReadXML/ReadXML/ReadXML.csproj +++ b/xml-csharp/ReadXML/ReadXML/ReadXML.csproj @@ -2,9 +2,13 @@ Exe - net8.0 + net10.0 enable enable + + + + diff --git a/xml-csharp/ReadXML/ReadXML/people.xml b/xml-csharp/ReadXML/ReadXML/people.xml new file mode 100644 index 0000000000..b5d531a5a6 --- /dev/null +++ b/xml-csharp/ReadXML/ReadXML/people.xml @@ -0,0 +1,35 @@ + + + + + Olivia + Davis + + olivia.davis@code-maze.com + 34 + + + + John + Davis + + john.davis@code-maze.com + 41 + + + + Sarah + Moore + + sarah.moore@code-maze.com + 27 + + + + Sarah + Smith + + sarah.smith@code-maze.com + 62 + + diff --git a/xml-csharp/ReadXML/Tests/Read/ReadXmlFromFileTests.cs b/xml-csharp/ReadXML/Tests/Read/ReadXmlFromFileTests.cs new file mode 100644 index 0000000000..dea1e14bdc --- /dev/null +++ b/xml-csharp/ReadXML/Tests/Read/ReadXmlFromFileTests.cs @@ -0,0 +1,46 @@ +namespace Tests.Read +{ + [TestClass] + public class ReadXmlFromFileTests + { + private static readonly string[] ExpectedEmails = + [ + "olivia.davis@code-maze.com", + "john.davis@code-maze.com", + "sarah.moore@code-maze.com", + "sarah.smith@code-maze.com" + ]; + + [TestMethod] + public void GivenPeopleFile_WhenCallingReadEmailsUsingXDocument_ThenAllEmailsAreReturned() + { + var result = ReadXmlFromFile.ReadEmailsUsingXDocument(ReadXmlFromFile.FilePath); + + CollectionAssert.AreEqual(ExpectedEmails, result.ToArray()); + } + + [TestMethod] + public void GivenPeopleFile_WhenCallingReadEmailsUsingXmlReader_ThenAllEmailsAreReturned() + { + var result = ReadXmlFromFile.ReadEmailsUsingXmlReader(ReadXmlFromFile.FilePath); + + CollectionAssert.AreEqual(ExpectedEmails, result.ToArray()); + } + + [TestMethod] + public void GivenPeopleFile_WhenCallingXmlDocumentReadEmails_ThenAllEmailsAreReturned() + { + var result = ReadXmlUsingXmlDocument.ReadEmails(ReadXmlFromFile.FilePath); + + CollectionAssert.AreEqual(ExpectedEmails, result.ToArray()); + } + + [TestMethod] + public void GivenMissingFile_WhenCallingXDocumentLoad_ThenFileNotFoundExceptionIsThrown() + { + var missing = Path.Combine(AppContext.BaseDirectory, "missing.xml"); + + Assert.ThrowsExactly(() => ReadXmlFromFile.ReadEmailsUsingXDocument(missing)); + } + } +} diff --git a/xml-csharp/ReadXML/Tests/Read/ReadXmlUsingXmlReaderTest.cs b/xml-csharp/ReadXML/Tests/Read/ReadXmlUsingXmlReaderTest.cs index 53388a1e49..af4ef08a1c 100644 --- a/xml-csharp/ReadXML/Tests/Read/ReadXmlUsingXmlReaderTest.cs +++ b/xml-csharp/ReadXML/Tests/Read/ReadXmlUsingXmlReaderTest.cs @@ -16,7 +16,7 @@ public void GivenValidXmlString_WhenCallingReadXml_ThenWhitespacesAreIsReturned( [TestMethod] public void GivenInvalidXmlString_WhenCallingReadXml_ThenExceptionIsThrown() { - Assert.ThrowsException(() => ReadXmlUsingXmlReader.ReadXml(CreateInvalidXmlString())); + Assert.ThrowsExactly(() => ReadXmlUsingXmlReader.ReadXml(CreateInvalidXmlString())); } @@ -41,7 +41,7 @@ public void GivenNumberOfPersons_WhenCallingCreateAnArrayOfPeople_ThenSameNumber var people = People.Get(numberOfPersons); var arrayOfPeople = CreateXmlUsingXmlWriter.CreateAnArrayOfPeople(people); - var result = ReadXmlUsingXmlReader.ReadNamesAndAges(arrayOfPeople); + var result = ReadXmlUsingXmlReader.ReadNamesAndSurnames(arrayOfPeople); Assert.AreEqual(numberOfPersons, result.Count()); } diff --git a/xml-csharp/ReadXML/Tests/Tests.csproj b/xml-csharp/ReadXML/Tests/Tests.csproj index cd4b734e78..597449a1be 100644 --- a/xml-csharp/ReadXML/Tests/Tests.csproj +++ b/xml-csharp/ReadXML/Tests/Tests.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable @@ -10,10 +10,10 @@ - - - - + + + +