Skip to content

Commit 488c608

Browse files
committed
Merge branch 'devel'
# Conflicts: # src/AngleSharp.XPath.Tests/AngleSharp.XPath.Tests.csproj # src/AngleSharp.XPath/AngleSharp.XPath.csproj
2 parents 704a8c9 + 36bd900 commit 488c608

File tree

4 files changed

+138
-31
lines changed

4 files changed

+138
-31
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<ItemGroup>
3-
<PackageReference Include="AngleSharp.Xml" Version="0.14.0" />
4-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
5-
<PackageReference Include="NUnit" Version="3.12.0" />
6-
<PackageReference Include="NUnit3TestAdapter" Version="3.16.1" />
3+
<PackageReference Include="AngleSharp.Xml" Version="0.17.0" />
4+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
5+
<PackageReference Include="NUnit" Version="3.13.3" />
6+
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
77
</ItemGroup>
88
<ItemGroup>
99
<ProjectReference Include="..\AngleSharp.XPath\AngleSharp.XPath.csproj" />
1010
</ItemGroup>
1111
<PropertyGroup>
12-
<TargetFramework>netcoreapp3.0</TargetFramework>
12+
<TargetFramework>net6.0</TargetFramework>
1313
<IsPackable>false</IsPackable>
1414
</PropertyGroup>
15-
</Project>
15+
</Project>

src/AngleSharp.XPath.Tests/HtmlDocumentNavigatorTests.cs

+74
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
using AngleSharp.Html.Parser;
44
using NUnit.Framework;
55
using System.Threading.Tasks;
6+
using System.Xml.XPath;
7+
using AngleSharp.Dom;
68

79
namespace AngleSharp.XPath.Tests
810
{
@@ -99,5 +101,77 @@ public void SelectSingleNode_DontIgnoreNamespaces_ShouldReturnNode()
99101
Assert.IsNotNull(node);
100102
Assert.That(node.NodeName, Is.EqualTo("xhtml:link"));
101103
}
104+
105+
[Test]
106+
public void SelectNodes_CanReturnAttribute()
107+
{
108+
// Arrange
109+
var html = "<!DOCTYPE html><html><body><div class=\"one\"><span class=\"two\">hello world</span></div></body></html>";
110+
var parser = new HtmlParser();
111+
var doc = parser.ParseDocument(html);
112+
113+
// Act
114+
var nodes = doc.DocumentElement.SelectNodes("//@*");
115+
116+
// Assert
117+
Assert.IsNotNull(nodes);
118+
Assert.That(nodes, Has.Count.EqualTo(2));
119+
Assert.That(nodes, Is.All.InstanceOf<Dom.IAttr>());
120+
}
121+
122+
[Test]
123+
public void TestNameXPathFunctionOnXMLDoc()
124+
{
125+
// Arrange
126+
var xml = @"<html><head><title>Test</title></head><body><h1>Test</h1></body></html>";
127+
var angleSharpXmlDoc = new XmlParser().ParseDocument(xml);
128+
129+
// Act
130+
var xmlNav = angleSharpXmlDoc.CreateNavigator();
131+
132+
// Assert
133+
Assert.AreEqual(TagNames.Html, xmlNav.Evaluate("name()"));
134+
}
135+
136+
[Test]
137+
public void TestNameXPathFunctionOnHTMLDoc()
138+
{
139+
// Arrange
140+
var html = @"<html><head><title>Test</title></head><body><h1>Test</h1></body></html>";
141+
142+
var angleSharpHtmlDoc = new HtmlParser().ParseDocument(html);
143+
144+
// Act
145+
var htmlNav = angleSharpHtmlDoc.CreateNavigator();
146+
147+
// Assert
148+
Assert.AreEqual(TagNames.Html, htmlNav.Evaluate("name()"));
149+
}
150+
151+
[Test]
152+
public void MoveToParent_CallWhenCurrentNodeIsAttr_ShouldBeMovedToAttrOwnerElement()
153+
{
154+
// Arrange
155+
var xml = @"<root att1='value 1' att2='value 2'><child>foo</child></root>";
156+
var parser = new XmlParser();
157+
var doc = parser.ParseDocument(xml);
158+
var nav = doc.CreateNavigator(false);
159+
nav.MoveToChild("root", "");
160+
161+
// Act
162+
163+
if (nav.MoveToFirstAttribute())
164+
{
165+
do
166+
{
167+
Assert.AreEqual(nav.NodeType, XPathNodeType.Attribute);
168+
}
169+
while (nav.MoveToNextAttribute());
170+
nav.MoveToParent();
171+
}
172+
173+
// Assert
174+
Assert.AreEqual(nav.Name, "root");
175+
}
102176
}
103177
}

src/AngleSharp.XPath/AngleSharp.XPath.csproj

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<Version>1.1.7</Version>
3+
<Version>2.0.0</Version>
4+
<AssemblyVersion>2.0.0</AssemblyVersion>
5+
<FileVersion>2.0.0</FileVersion>
46
<Authors>Denis Ivanov</Authors>
57
<PackageId>AngleSharp.XPath</PackageId>
6-
<AssemblyVersion>1.1.7</AssemblyVersion>
78
<AssemblyName>AngleSharp.XPath</AssemblyName>
89
<RootNamespace>AngleSharp.XPath</RootNamespace>
9-
<TargetFramework>netstandard2.0</TargetFramework>
10-
<FileVersion>1.1.7</FileVersion>
10+
<TargetFrameworks>netstandard2.0;net461;net472;net6.0</TargetFrameworks>
1111
<Description>XPath support for AngleSharp</Description>
1212
<PackageProjectUrl>https://github.com/AngleSharp/AngleSharp.XPath/</PackageProjectUrl>
1313
<PackageLicenseExpression>MIT</PackageLicenseExpression>
@@ -16,10 +16,15 @@
1616
<AssemblyOriginatorKeyFile>Key.snk</AssemblyOriginatorKeyFile>
1717
<GenerateDocumentationFile>true</GenerateDocumentationFile>
1818
<PublicSign>True</PublicSign>
19+
<PackageIconUrl>https://raw.githubusercontent.com/AngleSharp/AngleSharp.XPath/master/logo.png</PackageIconUrl>
1920
</PropertyGroup>
2021

2122
<ItemGroup>
22-
<PackageReference Include="AngleSharp" Version="0.14.0" />
23+
<PackageReference Include="AngleSharp" Version="0.17.0" />
24+
</ItemGroup>
25+
26+
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'net461' or '$(TargetFramework)' == 'net472' or '$(TargetFramework)' == 'net6.0' ">
27+
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" />
2328
</ItemGroup>
2429

2530
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT' ">

src/AngleSharp.XPath/HtmlDocumentNavigator.cs

+48-20
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ public class HtmlDocumentNavigator : XPathNavigator
1010
{
1111
private readonly IDocument _document;
1212
private INode _currentNode;
13-
private int _attrIndex;
1413
private readonly bool _ignoreNamespaces;
1514

1615
/// <summary>
@@ -24,7 +23,6 @@ public HtmlDocumentNavigator(IDocument document, INode currentNode, bool ignoreN
2423
_document = document ?? throw new ArgumentNullException(nameof(document));
2524
NameTable = new NameTable();
2625
_currentNode = currentNode ?? throw new ArgumentNullException(nameof(currentNode));
27-
_attrIndex = -1;
2826
_ignoreNamespaces = ignoreNamespaces;
2927
}
3028

@@ -49,15 +47,28 @@ public HtmlDocumentNavigator(IDocument document, INode currentNode, bool ignoreN
4947

5048
/// <inheritdoc />
5149
public override string LocalName =>
52-
_attrIndex != -1
53-
? NameTable.GetOrAdd(CurrentElement.Attributes[_attrIndex].LocalName)
50+
CurrentNode is IAttr attr
51+
? attr.LocalName
5452
: NameTable.GetOrAdd(CurrentNode is IElement e ? e.LocalName : string.Empty);
5553

5654
/// <inheritdoc />
57-
public override string Name =>
58-
_attrIndex != -1
59-
? NameTable.GetOrAdd(CurrentElement.Attributes[_attrIndex].Name)
60-
: NameTable.GetOrAdd(_currentNode.NodeName);
55+
public override string Name
56+
{
57+
get
58+
{
59+
if (CurrentNode is IAttr attr)
60+
{
61+
return NameTable.GetOrAdd(attr.Name);
62+
}
63+
64+
if (CurrentElement != null)
65+
{
66+
return NameTable.GetOrAdd(CurrentElement.LocalName);
67+
}
68+
69+
return NameTable.GetOrAdd(_currentNode.NodeName);
70+
}
71+
}
6172

6273
/// <inheritdoc />
6374
public override string NamespaceURI
@@ -69,16 +80,16 @@ public override string NamespaceURI
6980
return string.Empty;
7081
}
7182

72-
return _attrIndex != -1
73-
? NameTable.GetOrAdd(CurrentElement.Attributes[_attrIndex].NamespaceUri ?? string.Empty)
83+
return CurrentNode is IAttr attr
84+
? NameTable.GetOrAdd(attr.NamespaceUri ?? string.Empty)
7485
: NameTable.GetOrAdd(CurrentElement?.NamespaceUri ?? string.Empty);
7586
}
7687
}
7788

7889
/// <inheritdoc />
7990
public override string Prefix =>
80-
_attrIndex != 1
81-
? NameTable.GetOrAdd(CurrentElement.Attributes[_attrIndex].Prefix ?? string.Empty)
91+
CurrentNode is IAttr attr
92+
? NameTable.GetOrAdd(attr.Prefix ?? string.Empty)
8293
: NameTable.GetOrAdd(CurrentElement?.Prefix ?? string.Empty);
8394

8495
/// <inheritdoc />
@@ -107,7 +118,7 @@ public override XPathNodeType NodeType
107118
return XPathNodeType.Element;
108119

109120
case Dom.NodeType.Element:
110-
return _attrIndex != -1 ? XPathNodeType.Attribute : XPathNodeType.Element;
121+
return XPathNodeType.Element;
111122

112123
case Dom.NodeType.ProcessingInstruction:
113124
return XPathNodeType.ProcessingInstruction;
@@ -155,7 +166,7 @@ public override string Value
155166
return documentType.Name;
156167

157168
case Dom.NodeType.Element:
158-
return _attrIndex != -1 ? CurrentElement.Attributes[_attrIndex].Value : _currentNode.TextContent;
169+
return _currentNode.TextContent;
159170

160171
case Dom.NodeType.Entity:
161172
return _currentNode.TextContent;
@@ -207,7 +218,6 @@ public override bool MoveTo(XPathNavigator other)
207218
if (navigator._document == _document)
208219
{
209220
_currentNode = navigator._currentNode;
210-
_attrIndex = navigator._attrIndex;
211221
return true;
212222
}
213223

@@ -218,8 +228,8 @@ public override bool MoveTo(XPathNavigator other)
218228
public override bool MoveToFirstAttribute()
219229
{
220230
if (HasAttributes)
221-
{
222-
_attrIndex = 0;
231+
{
232+
_currentNode = CurrentElement.Attributes[0];
223233
return true;
224234
}
225235

@@ -278,12 +288,24 @@ public override bool MoveToNextAttribute()
278288
return false;
279289
}
280290

281-
if (_attrIndex >= CurrentElement.Attributes.Length - 1)
291+
if (!(CurrentNode is IAttr attr))
292+
{
293+
return false;
294+
}
295+
296+
if (attr.OwnerElement == null)
297+
{
298+
return false;
299+
}
300+
301+
var attrIndex = attr.OwnerElement.Attributes.Index(attr);
302+
303+
if (attrIndex >= CurrentElement.Attributes.Length - 1)
282304
{
283-
return false;
305+
return false;
284306
}
285307

286-
_attrIndex++;
308+
_currentNode = attr.OwnerElement.Attributes[attrIndex + 1];
287309
return true;
288310
}
289311

@@ -296,6 +318,12 @@ public override bool MoveToNextNamespace(XPathNamespaceScope namespaceScope)
296318
/// <inheritdoc />
297319
public override bool MoveToParent()
298320
{
321+
if (CurrentNode is IAttr attr)
322+
{
323+
_currentNode = attr.OwnerElement;
324+
return true;
325+
}
326+
299327
if (_currentNode.Parent == null)
300328
{
301329
return false;

0 commit comments

Comments
 (0)