Skip to content

Commit

Permalink
Merge pull request #506 from rwecho/master
Browse files Browse the repository at this point in the history
fix encapsulated item with corresponding ReturnType
  • Loading branch information
JonathanMagnan authored Jul 19, 2023
2 parents e4e5121 + 2930b38 commit 2cc71c3
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 84 deletions.
127 changes: 43 additions & 84 deletions src/HtmlAgilityPack.Shared/HtmlNode.Encapsulator.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Description: Html Agility Pack - HTML Parsers, selectors, traversors, manupulators.
// Description: Html Agility Pack - HTML Parsers, selectors, traversors, manupulators.
// Website & Documentation: http://html-agility-pack.net
// Forum & Issues: https://github.com/zzzprojects/html-agility-pack
// License: https://github.com/zzzprojects/html-agility-pack/blob/master/LICENSE
// More projects: http://www.zzzprojects.com/
// Copyright © ZZZ Projects Inc. 2014 - 2017. All rights reserved.
// Copyright © ZZZ Projects Inc. 2014 - 2017. All rights reserved.

#if !METRO && !NETSTANDARD1_3

Expand All @@ -29,7 +29,7 @@ public partial class HtmlNode
/// <exception cref="XPathException">Why it's thrown.</exception>
/// <exception cref="NodeNotFoundException">Why it's thrown.</exception>
/// <exception cref="NodeAttributeNotFoundException">Why it's thrown.</exception>
/// <exception cref="FormatException">Why it's thrown.</exception>
/// <exception cref="FormatException">Why it's thrown.</exception>
/// <exception cref="Exception">Why it's thrown.</exception>
public T GetEncapsulatedData<T>()
{
Expand All @@ -50,7 +50,7 @@ public T GetEncapsulatedData<T>()
/// <exception cref="XPathException">Why it's thrown.</exception>
/// <exception cref="NodeNotFoundException">Why it's thrown.</exception>
/// <exception cref="NodeAttributeNotFoundException">Why it's thrown.</exception>
/// <exception cref="FormatException">Why it's thrown.</exception>
/// <exception cref="FormatException">Why it's thrown.</exception>
/// <exception cref="Exception">Why it's thrown.</exception>
public T GetEncapsulatedData<T>(HtmlDocument htmlDocument)
{
Expand All @@ -72,7 +72,7 @@ public T GetEncapsulatedData<T>(HtmlDocument htmlDocument)
/// <exception cref="XPathException">Why it's thrown.</exception>
/// <exception cref="NodeNotFoundException">Why it's thrown.</exception>
/// <exception cref="NodeAttributeNotFoundException">Why it's thrown.</exception>
/// <exception cref="FormatException">Why it's thrown.</exception>
/// <exception cref="FormatException">Why it's thrown.</exception>
/// <exception cref="Exception">Why it's thrown.</exception>
public object GetEncapsulatedData(Type targetType, HtmlDocument htmlDocument = null)
{
Expand Down Expand Up @@ -177,7 +177,7 @@ public object GetEncapsulatedData(Type targetType, HtmlDocument htmlDocument = n
{
HtmlDocument innerHtmlDocument = new HtmlDocument();

innerHtmlDocument.LoadHtml(htmlNode.InnerHtml);
innerHtmlDocument.LoadHtml(Tools.GetHtmlForEncapsulation(htmlNode, xPathAttribute.NodeReturnType));

object o = GetEncapsulatedData(propertyInfo.PropertyType, innerHtmlDocument);

Expand All @@ -192,7 +192,7 @@ public object GetEncapsulatedData(Type targetType, HtmlDocument htmlDocument = n
{
string result = string.Empty;

if (xPathAttribute.AttributeName == null) // It target value of HTMLTag
if (xPathAttribute.AttributeName == null) // It target value of HTMLTag
{
result = Tools.GetNodeValueBasedOnXPathReturnType<string>(htmlNode, xPathAttribute);
}
Expand Down Expand Up @@ -295,7 +295,7 @@ public object GetEncapsulatedData(Type targetType, HtmlDocument htmlDocument = n
foreach (HtmlNode node in nodeCollection)
{
HtmlDocument innerHtmlDocument = new HtmlDocument();
innerHtmlDocument.LoadHtml(node.InnerHtml);
innerHtmlDocument.LoadHtml(Tools.GetHtmlForEncapsulation(node, xPathAttribute.NodeReturnType));

object o = GetEncapsulatedData(T_Types[0], innerHtmlDocument);

Expand Down Expand Up @@ -381,9 +381,6 @@ public object GetEncapsulatedData(Type targetType, HtmlDocument htmlDocument = n
}
#endregion targetObject_NOTDefined_XPath
}



}


Expand Down Expand Up @@ -602,34 +599,7 @@ internal static T GetNodeValueBasedOnXPathReturnType<T>(HtmlNode htmlNode, XPath
throw new ArgumentNullException("parameter xpathAttribute is null");
}

object result;
Type TType = typeof(T);

switch (xPathAttribute.NodeReturnType)
{
case ReturnType.InnerHtml:
{
result = Convert.ChangeType(htmlNode.InnerHtml, TType);
}
break;


case ReturnType.InnerText:
{
result = Convert.ChangeType(htmlNode.InnerText, TType);
}
break;

case ReturnType.OuterHtml:
{
result = Convert.ChangeType(htmlNode.OuterHtml, TType);
}
break;

default: throw new Exception();
}

return (T)result;
return (T)Convert.ChangeType(GetHtmlForEncapsulation(htmlNode, xPathAttribute.NodeReturnType), typeof(T));
}


Expand All @@ -654,41 +624,10 @@ internal static IList GetNodesValuesBasedOnXPathReturnType(HtmlNodeCollection ht


IList result = listGenericType.CreateIListOfType();

switch (xPathAttribute.NodeReturnType)
foreach (HtmlNode node in htmlNodeCollection)
{

case ReturnType.InnerHtml:
{
foreach (HtmlNode node in htmlNodeCollection)
{
result.Add(Convert.ChangeType(node.InnerHtml, listGenericType));
}
}
break;


case ReturnType.InnerText:
{
foreach (HtmlNode node in htmlNodeCollection)
{
result.Add(Convert.ChangeType(node.InnerText, listGenericType));
}
}
break;


case ReturnType.OuterHtml:
{
foreach (HtmlNode node in htmlNodeCollection)
{
result.Add(Convert.ChangeType(node.OuterHtml, listGenericType));
}
}
break;

result.Add(Convert.ChangeType(GetHtmlForEncapsulation(node, xPathAttribute.NodeReturnType), listGenericType));
}

return result;
}

Expand Down Expand Up @@ -787,7 +726,27 @@ internal static int CountOfIEnumerable<T>(this IEnumerable<T> source)
return counter;
}


/// <summary>
/// Return html part of <see cref="HtmlNode"/> based on <see cref="ReturnType"/>
/// </summary>
/// <param name="node">A htmlNode instance.</param>
/// <param name="returnType"><see cref="ReturnType"/></param>
/// <returns>Html part</returns>
/// <exception cref="IndexOutOfRangeException">Out of range to the <see cref="ReturnType"/></exception>
internal static string GetHtmlForEncapsulation(HtmlNode node, ReturnType returnType)
{
switch (returnType)
{
case ReturnType.InnerText:
return node.InnerText;
case ReturnType.InnerHtml:
return node.InnerHtml;
case ReturnType.OuterHtml:
return node.OuterHtml;
default:
throw new IndexOutOfRangeException("Unhandled ReturnType : " + returnType.ToString());
};
}
}


Expand All @@ -797,7 +756,7 @@ internal static int CountOfIEnumerable<T>(this IEnumerable<T> source)
public enum ReturnType
{
/// <summary>
/// The text between the start and end tags of the object.
/// The text between the start and end tags of the object.
/// </summary>
InnerText,

Expand Down Expand Up @@ -896,18 +855,18 @@ public sealed class SkipNodeNotFoundAttribute : Attribute
public class NodeNotFoundException : Exception
{
/// <summary>
///
///
/// </summary>
public NodeNotFoundException() { }

/// <summary>
///
///
/// </summary>
/// <param name="message"></param>
public NodeNotFoundException(string message) : base(message) { }

/// <summary>
///
///
/// </summary>
/// <param name="message"></param>
/// <param name="inner"></param>
Expand All @@ -921,18 +880,18 @@ public NodeNotFoundException(string message, Exception inner) : base(message, in
public class NodeAttributeNotFoundException : Exception
{
/// <summary>
///
///
/// </summary>
public NodeAttributeNotFoundException() { }

/// <summary>
///
///
/// </summary>
/// <param name="message"></param>
public NodeAttributeNotFoundException(string message) : base(message) { }

/// <summary>
///
///
/// </summary>
/// <param name="message"></param>
/// <param name="inner"></param>
Expand All @@ -947,18 +906,18 @@ public class MissingXPathException : Exception
{

/// <summary>
///
///
/// </summary>
public MissingXPathException() { }

/// <summary>
///
///
/// </summary>
/// <param name="message"></param>
public MissingXPathException(string message) : base(message) { }

/// <summary>
///
///
/// </summary>
/// <param name="message"></param>
/// <param name="inner"></param>
Expand All @@ -967,7 +926,7 @@ public MissingXPathException(string message, Exception inner) : base(message, in

}

#if FX20
#if FX20
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
using Xunit;

namespace HtmlAgilityPack.Tests.NetStandard2_0
Expand Down Expand Up @@ -29,8 +30,32 @@ public void Dictionary_Test()

Assert.NotNull(wort);
}

[Fact]
public void EncapsulatedOuterHtml_Test()
{
var html = @"
<div>
<a href='3.html' class='single'>3</a>
<div>hello
<a href='1.html'>1</a>
<a href='2.html'>2</a>
</div>
<div>world</div>
</div>
";
var document = new HtmlDocument();
document.LoadHtml(html);
var outerHtml = document.DocumentNode.GetEncapsulatedData<OuterHtml>();
Assert.True(outerHtml.Item3.Href == "3.html");
Assert.True(outerHtml.Item3.Name == "3");

Assert.True(outerHtml.Items.Count == 3);
Assert.True(outerHtml.Items.All(o => o.Href != null));
}
}


#region StackOverFlow_TestClasses

[HasXPath]
Expand Down Expand Up @@ -204,5 +229,29 @@ public class Example

#endregion Dictionary_TestClasses

#region Encapsulated outer html test classes

[HasXPath]
public class OuterHtml
{
[XPath("//a", ReturnType.OuterHtml)]
public List<OuterHtmlItem> Items { get; set; }

[XPath("//a[@class='single']", ReturnType.OuterHtml)]
public OuterHtmlItem Item3 { get; set; }


[HasXPath]
public class OuterHtmlItem
{
[XPath("a", "href")]
[SkipNodeNotFound]
public string Href { get; set; }

[XPath("a")]
[SkipNodeNotFound]
public string Name { get; set; }
}
}
#endregion
}

0 comments on commit 2cc71c3

Please sign in to comment.