Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
using SelectingXmlNodesWithXpath;
using System.Xml;
using System.Xml.Linq;

var path = Path.Combine(AppContext.BaseDirectory, "BooksCatalog.xml");

var doc = new XmlDocument();
doc.Load("BooksCatalog.xml");
doc.Load(path);
var root = doc.DocumentElement!;

Console.WriteLine("Selected book:");
var singleResult = XmlNodesSelector.SelectSingleBook(root);
Console.WriteLine(singleResult);
Console.WriteLine(singleResult ?? "No book matched the query.");

Console.WriteLine("\nSelected books:");
var results = XmlNodesSelector.SelectBooks(root);
results.ForEach(Console.WriteLine);

Console.WriteLine("\nSelected books:");
var resultsFromNamespaces = XmlNodesSelector.SelectBooksUsingNamespaces(doc);
resultsFromNamespaces.ForEach(Console.WriteLine);
resultsFromNamespaces.ForEach(Console.WriteLine);

Console.WriteLine("\nSelected books with LINQ to XML:");
var linqResults = XmlNodesSelector.SelectBooksWithLinqToXml(XDocument.Load(path));
linqResults.ForEach(Console.WriteLine);
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;

namespace SelectingXmlNodesWithXpath;

Expand All @@ -10,18 +11,23 @@ public static string FormatXml(string unformattedXml)
return XElement.Parse(unformattedXml).ToString();
}

public static string SelectSingleBook(XmlNode root)
public static string? SelectSingleBook(XmlNode root)
{
var node = root.SelectSingleNode("//catalog/book[position()=2]");
return FormatXml(node!.OuterXml);

return node is null ? null : FormatXml(node.OuterXml);
}

public static List<string> SelectBooks(XmlNode root)
{
var nodes = root.SelectNodes("//catalog/book[price<50.00]");

return nodes!
if (nodes is null)
{
return [];
}

return nodes
.Cast<XmlNode>()
.Select(x => FormatXml(x.OuterXml))
.ToList();
Expand All @@ -34,9 +40,22 @@ public static List<string> SelectBooksUsingNamespaces(XmlDocument doc)

var nodes = doc.SelectNodes("descendant::ex:book", nsmgr);

return nodes!
if (nodes is null)
{
return [];
}

return nodes
.Cast<XmlNode>()
.Select(x => FormatXml(x.OuterXml))
.ToList();
}

public static List<string> SelectBooksWithLinqToXml(XDocument doc)
{
return doc
.XPathSelectElements("//catalog/book[price<50.00]")
.Select(x => x.ToString())
.ToList();
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
global using SelectingXmlNodesWithXpath;
global using System.Xml;
global using Xunit;
global using Xunit;
global using System.Xml.Linq;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

Expand All @@ -16,13 +16,13 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.10.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.2.0">
<PackageReference Include="coverlet.collector" Version="10.0.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,20 @@ public void GivenAnXmlFile_WhenSelectingASingleNode_ThenReturnsTheSecondPosition
{
var result = XmlNodesSelector.SelectSingleBook(_document.DocumentElement!);

Assert.Equal(result, _expectedResults["Book2"]);
Assert.Equal(result?.ReplaceLineEndings(), _expectedResults["Book2"].ReplaceLineEndings());
}

[Fact]
public void GivenAnXmlFile_WhenSelectingNodes_ThenReturnBooksWithPriceLowerThan50()
{
var expected = _expectedResults
.Where(pair => pair.Key is "Book1" or "Book3")
.Select(pair => pair.Value)
.Select(pair => pair.Value.ReplaceLineEndings())
.ToList();

var result = XmlNodesSelector.SelectBooks(_document.DocumentElement!);
var result = XmlNodesSelector.SelectBooks(_document.DocumentElement!)
.Select(x => x.ReplaceLineEndings())
.ToList();

Assert.Equal(result, expected);
}
Expand All @@ -86,11 +88,53 @@ public void GivenAnXmlFile_WhenSelectingNodesUsingNamespaces_ThenReturnBookEleme
var expected =
_expectedResults
.Where(pair => pair.Key is "Book4")
.Select(pair => pair.Value)
.Select(pair => pair.Value.ReplaceLineEndings())
.ToList();

var result = XmlNodesSelector.SelectBooksUsingNamespaces(_document);
var result = XmlNodesSelector.SelectBooksUsingNamespaces(_document)
.Select(x => x.ReplaceLineEndings())
.ToList();

Assert.Equal(result, expected);
}
}

[Fact]
public void GivenAnXmlFile_WhenSelectSingleNodeMatchesNothing_ThenReturnsNull()
{
var node = _document.DocumentElement!.SelectSingleNode("//catalog/book[price>1000]");

Assert.Null(node);
}

[Fact]
public void GivenAnXmlFile_WhenSelectNodesMatchesNothing_ThenReturnsAnEmptyList()
{
var nodes = _document.DocumentElement!.SelectNodes("//catalog/book[price>1000]");

Assert.NotNull(nodes);
Assert.Equal(0, nodes.Count);
}

[Fact]
public void GivenABookInADefaultNamespace_WhenQueryingWithAnUnprefixedName_ThenReturnsThreeOfTheFourBooks()
{
var nodes = _document.DocumentElement!.SelectNodes("//catalog/book");

Assert.NotNull(nodes);
Assert.Equal(3, nodes.Count);
}

[Fact]
public void GivenAnXDocument_WhenSelectingWithXPathSelectElements_ThenReturnsTheSameBooksAsSelectNodes()
{
var expected = XmlNodesSelector.SelectBooks(_document.DocumentElement!)
.Select(x => x.ReplaceLineEndings())
.ToList();

var result = XmlNodesSelector.SelectBooksWithLinqToXml(XDocument.Load("BooksCatalog.xml"))
.Select(x => x.ReplaceLineEndings())
.ToList();

Assert.Equal(expected, result);
}
}
Loading