Permalink
Browse files

add samples to the readme; rename HTMLTag.Name to Type; make HTMLDocu…

…ment point at the first actual node not #document; add HTMLTagTypeFilter
  • Loading branch information...
1 parent 16b3c3e commit 6fbff4b02d96dfefccdaabfca3a2f794a38b5789 @handcraftsman handcraftsman committed Jul 16, 2010
View
40 README.md
@@ -1,10 +1,46 @@
-A simple utility that lets you use LINQ syntax to query HTML instead of XSLT. We use it in unit tests to verify that generated HTML correctly represents the generation inputs.
+A simple utility that lets you use LINQ syntax to query HTML.
## Samples
+ const string html = "<html><head><TITLE>The Title</TITLE></head><body>Hello World</body></html>";
+ var parsed = HTMLParser.Parse(html);
+
+ parsed
+ .DescendantTags
+ .OfType("title").IgnoreCase()
+ .Any()
+ .ShouldBeTrue();
+ parsed
+ .DescendantTags
+ .OfType("title")
+ .Any()
+ .ShouldBeFalse();
-## License
+ parsed
+ .ChildTags
+ .Count()
+ .ShouldBeEqualTo(2); // head, body
+
+ parsed
+ .DescendantTags
+ .OfType("title").IgnoreCase()
+ .First()
+ .Parent
+ .TypeEqualsIgnoreCase("HEAD")
+ .ShouldBeTrue();
+
+ parsed
+ .DescendantTags
+ .Count(x => x.Parent.TypeEqualsIgnoreCase("HTML"))
+ .ShouldBeEqualTo(2); // head, body
+
+ parsed
+ .Body
+ .Content
+ .ShouldBeEqualTo("Hello World");
+
+## License
[MIT License][mitlicense]
View
20 src/LinqToHtml.Tests/HTMLDocumentTests.cs
@@ -10,7 +10,7 @@ namespace LinqToHtml.Tests
public class HTMLDocumentTests
{
[TestFixture]
- public class When_asked_for_all_descendant_tags
+ public class When_asked_for_its_descendant_tags
{
private int _expectedTagCount;
private string _html;
@@ -21,7 +21,7 @@ public void Given_a_basic_html_document()
{
Test.Verify(
with_a_basic_html_document,
- when_asked_for_all_descendant_tags,
+ when_asked_for_its_descendant_tags,
should_not_return_null,
should_not_return_an_empty_list,
should_return_the_correct_number_of_tags,
@@ -43,7 +43,7 @@ private void should_not_return_null()
private void should_return_the_body_tag()
{
- _result.Single(x => x.Name == "body");
+ _result.Single(x => x.Type == "body");
}
private void should_return_the_correct_number_of_tags()
@@ -53,24 +53,24 @@ private void should_return_the_correct_number_of_tags()
private void should_return_the_head_tag()
{
- _result.Single(x => x.Name == "head");
+ _result.Single(x => x.Type == "head");
}
private void should_return_the_title_tag()
{
- _result.Single(x => x.Name == "title");
+ _result.Single(x => x.Type == "title");
}
- private void when_asked_for_all_descendant_tags()
+ private void when_asked_for_its_descendant_tags()
{
_result = HTMLParser.Parse(_html)
- .AllDescendantTags.ToList();
+ .DescendantTags.ToList();
}
private void with_a_basic_html_document()
{
_html = "<html><head><title>The Title</title></head><body>Hello World</body></html>";
- _expectedTagCount = 4; // html, head, title, body
+ _expectedTagCount = 3; // head, title, body
}
}
@@ -109,7 +109,7 @@ private void should_not_return_null()
private void should_return_the_BODY_tag()
{
- _result.NameEqualsIgnoreCase("BODY").ShouldBeTrue();
+ _result.TypeEqualsIgnoreCase("BODY").ShouldBeTrue();
}
private void when_asked_for_the_BODY_tag()
@@ -163,7 +163,7 @@ private void should_not_return_null()
private void should_return_the_HEAD_tag()
{
- _result.NameEqualsIgnoreCase("HEAD").ShouldBeTrue();
+ _result.TypeEqualsIgnoreCase("HEAD").ShouldBeTrue();
}
private void when_asked_for_the_HEAD_tag()
View
10 src/LinqToHtml.Tests/HTMLParserTests.cs
@@ -9,7 +9,7 @@ public class HTMLParserTests
[TestFixture]
public class When_asked_to_parse_an_HTML_string
{
- private string _expectedName;
+ private string _expectedType;
private string _html;
private HTMLTag _result;
@@ -20,7 +20,7 @@ public void Given_a_basic_html_document()
with_a_basic_html_document,
when_asked_to_parse_the_string,
should_not_return_null,
- should_return_an_html_document_with_the_correct_Name
+ should_return_an_html_document_with_the_correct_Type
);
}
@@ -29,9 +29,9 @@ private void should_not_return_null()
_result.ShouldNotBeNull();
}
- private void should_return_an_html_document_with_the_correct_Name()
+ private void should_return_an_html_document_with_the_correct_Type()
{
- _result.Name.ShouldBeEqualTo(_expectedName);
+ _result.Type.ShouldBeEqualTo(_expectedType);
}
private void when_asked_to_parse_the_string()
@@ -42,7 +42,7 @@ private void when_asked_to_parse_the_string()
private void with_a_basic_html_document()
{
_html = "<html><head><title>The Title</title></head><body>Hello World</body></html>";
- _expectedName = HTMLDocument.DefaultName;
+ _expectedType = "html";
}
}
}
View
1 src/LinqToHtml.Tests/HTMLTagAttributeExtensionsTests.cs
@@ -58,7 +58,6 @@ private void should_return_true()
private void when_asked_if_its_name_equals_ignore_case()
{
_result = HTMLParser.Parse("<body " + _attributeName + "='foo' />")
- .ChildTags.First()
.Attributes.First().NameEqualsIgnoreCase(_name);
}
View
55 src/LinqToHtml.Tests/HTMLTagExtensionsTests.cs
@@ -1,5 +1,3 @@
-using System.Linq;
-
using FluentAssert;
using NUnit.Framework;
@@ -9,39 +7,39 @@ namespace LinqToHtml.Tests
public class HTMLTagExtensionsTests
{
[TestFixture]
- public class When_asked_if_its_name_equals_ignore_case
+ public class When_asked_if_its_type_equals_ignore_case
{
- private string _name;
private bool _result;
- private string _tagName;
+ private string _tagType;
+ private string _type;
[Test]
- public void Given_the_name_has_different_case()
+ public void Given_the_type_has_different_case()
{
Test.Verify(
- with_a_name_that_differs_only_by_case,
- when_asked_if_its_name_equals_ignore_case,
+ with_a_type_that_differs_only_by_case,
+ when_asked_if_its_type_equals_ignore_case,
should_return_true
);
}
[Test]
- public void Given_the_name_matches_exactly()
+ public void Given_the_type_is_completely_different()
{
Test.Verify(
- with_a_name_that_matches_exactly,
- when_asked_if_its_name_equals_ignore_case,
- should_return_true
+ with_a_type_that_is_completely_different,
+ when_asked_if_its_type_equals_ignore_case,
+ should_return_false
);
}
[Test]
- public void Given_the_name_that_is_completely_different()
+ public void Given_the_type_matches_exactly()
{
Test.Verify(
- with_a_name_that_is_completely_different,
- when_asked_if_its_name_equals_ignore_case,
- should_return_false
+ with_a_type_that_matches_exactly,
+ when_asked_if_its_type_equals_ignore_case,
+ should_return_true
);
}
@@ -55,29 +53,28 @@ private void should_return_true()
_result.ShouldBeTrue();
}
- private void when_asked_if_its_name_equals_ignore_case()
+ private void when_asked_if_its_type_equals_ignore_case()
{
- _result = HTMLParser.Parse("<" + _tagName + " />")
- .ChildTags.First()
- .NameEqualsIgnoreCase(_name);
+ _result = HTMLParser.Parse("<" + _tagType + " />")
+ .TypeEqualsIgnoreCase(_type);
}
- private void with_a_name_that_differs_only_by_case()
+ private void with_a_type_that_differs_only_by_case()
{
- _name = "HeAd";
- _tagName = "head";
+ _type = "HeAd";
+ _tagType = "head";
}
- private void with_a_name_that_is_completely_different()
+ private void with_a_type_that_is_completely_different()
{
- _name = "HeAd";
- _tagName = "tail";
+ _type = "HeAd";
+ _tagType = "tail";
}
- private void with_a_name_that_matches_exactly()
+ private void with_a_type_that_matches_exactly()
{
- _name = "HeAd";
- _tagName = _name;
+ _type = "HeAd";
+ _tagType = _type;
}
}
}
View
228 src/LinqToHtml.Tests/HTMLTagTests.cs
@@ -11,71 +11,6 @@ namespace LinqToHtml.Tests
public class HTMLTagTests
{
[TestFixture]
- public class When_asked_for_all_descendant_tags
- {
- private int _expectedTagCount;
- private string _html;
- private List<HTMLTag> _result;
-
- [Test]
- public void Given_a_basic_html_document()
- {
- Test.Verify(
- with_a_basic_html_document,
- when_asked_for_all_descendant_tags,
- should_not_return_null,
- should_not_return_an_empty_list,
- should_return_the_correct_number_of_tags,
- should_return_the_head_tag,
- should_return_the_title_tag,
- should_return_the_body_tag
- );
- }
-
- private void should_not_return_an_empty_list()
- {
- _result.Count.ShouldNotBeEqualTo(0);
- }
-
- private void should_not_return_null()
- {
- _result.ShouldNotBeNull();
- }
-
- private void should_return_the_body_tag()
- {
- _result.Single(x => x.Name == "body");
- }
-
- private void should_return_the_correct_number_of_tags()
- {
- _result.Count.ShouldBeEqualTo(_expectedTagCount);
- }
-
- private void should_return_the_head_tag()
- {
- _result.Single(x => x.Name == "head");
- }
-
- private void should_return_the_title_tag()
- {
- _result.Single(x => x.Name == "title");
- }
-
- private void when_asked_for_all_descendant_tags()
- {
- _result = HTMLParser.Parse(_html)
- .AllDescendantTags.ToList();
- }
-
- private void with_a_basic_html_document()
- {
- _html = "<html><head><title>The Title</title></head><body>Hello World</body></html>";
- _expectedTagCount = 4; // html, head, title, body
- }
- }
-
- [TestFixture]
public class When_asked_for_its_attributes
{
private int _expectedAttributeCount;
@@ -174,7 +109,8 @@ public void Given_a_basic_html_document()
should_not_return_null,
should_not_return_an_empty_list,
should_return_the_correct_number_of_tags,
- should_return_the_html_tag
+ should_return_the_head_tag,
+ should_return_the_body_tag
);
}
@@ -188,14 +124,19 @@ private void should_not_return_null()
_result.ShouldNotBeNull();
}
+ private void should_return_the_body_tag()
+ {
+ _result.Single(x => x.Type == "body");
+ }
+
private void should_return_the_correct_number_of_tags()
{
_result.Count.ShouldBeEqualTo(_expectedTagCount);
}
- private void should_return_the_html_tag()
+ private void should_return_the_head_tag()
{
- _result.Single(x => x.Name == "html");
+ _result.Single(x => x.Type == "head");
}
private void when_asked_for_its_child_tags()
@@ -207,7 +148,156 @@ private void when_asked_for_its_child_tags()
private void with_a_basic_html_document()
{
_html = "<html><head><title>The Title</title></head><body>Hello World</body></html>";
- _expectedTagCount = 1; // html
+ _expectedTagCount = 2; // head, body
+ }
+ }
+
+ [TestFixture]
+ public class When_asked_for_its_content
+ {
+ private string _result;
+ private HTMLTag _tag;
+
+ [Test]
+ public void Given_a_tag_that_has_content()
+ {
+ Test.Verify(
+ with_a_tag_that_has_content,
+ when_asked_for_its_content,
+ should_not_return_null,
+ should_return_the_content
+ );
+ }
+
+ private void should_not_return_null()
+ {
+ _result.ShouldNotBeNull();
+ }
+
+ private void should_return_the_content()
+ {
+ _result.ShouldBeEqualTo("The Title");
+ }
+
+ private void when_asked_for_its_content()
+ {
+ _result = _tag.Content;
+ }
+
+ private void with_a_tag_that_has_content()
+ {
+ const string html = "<html><head><title>The Title</title></head><body>Hello World</body></html>";
+ _tag = HTMLParser.Parse(html)
+ .DescendantTags
+ .OfType("title")
+ .First();
+ }
+ }
+
+ [TestFixture]
+ public class When_asked_for_its_descendant_tags
+ {
+ private int _expectedTagCount;
+ private string _html;
+ private List<HTMLTag> _result;
+
+ [Test]
+ public void Given_a_basic_html_document()
+ {
+ Test.Verify(
+ with_a_basic_html_document,
+ when_asked_for_its_descendant_tags,
+ should_not_return_null,
+ should_not_return_an_empty_list,
+ should_return_the_correct_number_of_tags,
+ should_return_the_head_tag,
+ should_return_the_title_tag,
+ should_return_the_body_tag
+ );
+ }
+
+ private void should_not_return_an_empty_list()
+ {
+ _result.Count.ShouldNotBeEqualTo(0);
+ }
+
+ private void should_not_return_null()
+ {
+ _result.ShouldNotBeNull();
+ }
+
+ private void should_return_the_body_tag()
+ {
+ _result.Single(x => x.Type == "body");
+ }
+
+ private void should_return_the_correct_number_of_tags()
+ {
+ _result.Count.ShouldBeEqualTo(_expectedTagCount);
+ }
+
+ private void should_return_the_head_tag()
+ {
+ _result.Single(x => x.Type == "head");
+ }
+
+ private void should_return_the_title_tag()
+ {
+ _result.Single(x => x.Type == "title");
+ }
+
+ private void when_asked_for_its_descendant_tags()
+ {
+ _result = HTMLParser.Parse(_html)
+ .DescendantTags.ToList();
+ }
+
+ private void with_a_basic_html_document()
+ {
+ _html = "<html><head><title>The Title</title></head><body>Hello World</body></html>";
+ _expectedTagCount = 3; // head, title, body
+ }
+ }
+
+ [TestFixture]
+ public class When_asked_for_its_parent_tag
+ {
+ private HTMLTag _result;
+ private HTMLTag _tag;
+
+ [Test]
+ public void Given_a_tag_that_has_a_parent()
+ {
+ Test.Verify(
+ with_a_tag_that_has_a_parent,
+ when_asked_for_its_parent_tag,
+ should_not_return_null,
+ should_return_the_parent_tag
+ );
+ }
+
+ private void should_not_return_null()
+ {
+ _result.ShouldNotBeNull();
+ }
+
+ private void should_return_the_parent_tag()
+ {
+ _result.Type.ShouldBeEqualTo("head");
+ }
+
+ private void when_asked_for_its_parent_tag()
+ {
+ _result = _tag.Parent;
+ }
+
+ private void with_a_tag_that_has_a_parent()
+ {
+ const string html = "<html><head><title>The Title</title></head><body>Hello World</body></html>";
+ _tag = HTMLParser.Parse(html)
+ .DescendantTags
+ .OfType("title")
+ .First();
}
}
}
View
147 src/LinqToHtml.Tests/HTMLTagTypeFilterTests.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using FluentAssert;
+
+using NUnit.Framework;
+
+namespace LinqToHtml.Tests
+{
+ public class HTMLTagTypeFilterTests
+ {
+ [TestFixture]
+ public class When_asked_to_get_the_tags
+ {
+ private IEnumerable<HTMLTag> _list;
+ private IEnumerable<HTMLTag> _result;
+ private string _type;
+
+ [Test]
+ public void Given_a_list_that_contains_the_requested_tag_type_with_a_different_case()
+ {
+ Test.Verify(
+ with_a_list_that_contains_various_tags,
+ with_a_type_that_is_in_the_list_with_a_different_case,
+ when_asked_to_get_the_tags_for_the_requested_type,
+ should_not_return_null,
+ should_return_an_empty_list
+ );
+ }
+
+ [Test]
+ public void Given_a_list_that_contains_the_requested_tag_type_with_the_same_case()
+ {
+ Test.Verify(
+ with_a_list_that_contains_various_tags,
+ with_a_type_that_is_in_the_list_with_the_same_case,
+ when_asked_to_get_the_tags_for_the_requested_type,
+ should_not_return_null,
+ should_return_only_the_matching_tags
+ );
+ }
+
+ private void should_not_return_null()
+ {
+ _result.ShouldNotBeNull();
+ }
+
+ private void should_return_an_empty_list()
+ {
+ _result.Count().ShouldBeEqualTo(0);
+ }
+
+ private void should_return_only_the_matching_tags()
+ {
+ var enumerable = _result.Select(x => x.Type).Distinct();
+ enumerable.Count().ShouldBeEqualTo(1);
+ enumerable.First().ShouldBeEqualTo(_type);
+ }
+
+ private void when_asked_to_get_the_tags_for_the_requested_type()
+ {
+ _result = _list.OfType(_type).ToList();
+ }
+
+ private void with_a_list_that_contains_various_tags()
+ {
+ _list = HTMLParser.Parse("<html><a/><b/><c/><d/><a/><b/><c/><d/></html>").ChildTags;
+ }
+
+ private void with_a_type_that_is_in_the_list_with_a_different_case()
+ {
+ _type = "B";
+ }
+
+ private void with_a_type_that_is_in_the_list_with_the_same_case()
+ {
+ _type = "b";
+ }
+ }
+
+ [TestFixture]
+ public class When_asked_to_get_the_tags_ignoring_case
+ {
+ private IEnumerable<HTMLTag> _list;
+ private IEnumerable<HTMLTag> _result;
+ private string _type;
+
+ [Test]
+ public void Given_a_list_that_contains_the_requested_tag_type_with_a_different_case()
+ {
+ Test.Verify(
+ with_a_list_that_contains_various_tags,
+ with_a_type_that_is_in_the_list_with_a_different_case,
+ when_asked_to_get_the_tags_for_the_requested_type,
+ should_not_return_null,
+ should_return_only_the_matching_tags_ignoring_case
+ );
+ }
+
+ [Test]
+ public void Given_a_list_that_contains_the_requested_tag_type_with_the_same_case()
+ {
+ Test.Verify(
+ with_a_list_that_contains_various_tags,
+ with_a_type_that_is_in_the_list_with_the_same_case,
+ when_asked_to_get_the_tags_for_the_requested_type,
+ should_not_return_null,
+ should_return_only_the_matching_tags_ignoring_case
+ );
+ }
+
+ private void should_not_return_null()
+ {
+ _result.ShouldNotBeNull();
+ }
+
+ private void should_return_only_the_matching_tags_ignoring_case()
+ {
+ var enumerable = _result.Select(x => x.Type).Distinct();
+ enumerable.Count().ShouldBeEqualTo(1);
+ string type = enumerable.First();
+ String.Equals(type, _type, StringComparison.InvariantCultureIgnoreCase).ShouldBeTrue();
+ }
+
+ private void when_asked_to_get_the_tags_for_the_requested_type()
+ {
+ _result = _list.OfType(_type).IgnoreCase().ToList();
+ }
+
+ private void with_a_list_that_contains_various_tags()
+ {
+ _list = HTMLParser.Parse("<html><a/><b/><c/><d/><a/><b/><c/><d/></html>").ChildTags;
+ }
+
+ private void with_a_type_that_is_in_the_list_with_a_different_case()
+ {
+ _type = "B";
+ }
+
+ private void with_a_type_that_is_in_the_list_with_the_same_case()
+ {
+ _type = "b";
+ }
+ }
+ }
+}
View
59 src/LinqToHtml.Tests/IEnumerableHTMLTagExtensionsTests.cs
@@ -0,0 +1,59 @@
+using System.Collections.Generic;
+using System.Linq;
+
+using FluentAssert;
+
+using NUnit.Framework;
+
+namespace LinqToHtml.Tests
+{
+ public class IEnumerableHTMLTagExtensionsTests
+ {
+ [TestFixture]
+ public class When_asked_to_get_the_tags_of_a_certain_type
+ {
+ private IEnumerable<HTMLTag> _list;
+ private IEnumerable<HTMLTag> _result;
+ private string _type;
+
+ [Test]
+ public void Given_a_list_that_contains_the_requested_tag_type()
+ {
+ Test.Verify(
+ with_a_list_that_contains_various_tags,
+ with_a_type_that_is_in_the_list,
+ when_asked_to_get_the_tags_for_the_requested_type,
+ should_not_return_null,
+ should_return_only_the_matching_tags
+ );
+ }
+
+ private void should_not_return_null()
+ {
+ _result.ShouldNotBeNull();
+ }
+
+ private void should_return_only_the_matching_tags()
+ {
+ var enumerable = _result.Select(x => x.Type).Distinct();
+ enumerable.Count().ShouldBeEqualTo(1);
+ enumerable.First().ShouldBeEqualTo(_type);
+ }
+
+ private void when_asked_to_get_the_tags_for_the_requested_type()
+ {
+ _result = _list.OfType(_type).ToList();
+ }
+
+ private void with_a_list_that_contains_various_tags()
+ {
+ _list = HTMLParser.Parse("<html><a/><b/><c/><d/><a/><b/><c/><d/></html>").ChildTags;
+ }
+
+ private void with_a_type_that_is_in_the_list()
+ {
+ _type = "b";
+ }
+ }
+ }
+}
View
2 src/LinqToHtml.Tests/LinqToHtml.Tests.csproj
@@ -59,6 +59,8 @@
<Compile Include="HTMLTagAttributeTests.cs" />
<Compile Include="HTMLTagExtensionsTests.cs" />
<Compile Include="HTMLTagTests.cs" />
+ <Compile Include="HTMLTagTypeFilterTests.cs" />
+ <Compile Include="IEnumerableHTMLTagExtensionsTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
View
17 src/LinqToHtml/HTMLDocument.cs
@@ -6,14 +6,13 @@ namespace LinqToHtml
{
public class HTMLDocument : HTMLTag
{
- public const string DefaultName = "#document";
private HTMLTag _body;
private bool _fetchedBody;
private bool _fetchedHead;
private HTMLTag _head;
public HTMLDocument(XmlDocument document)
- : base(document)
+ : base(document.FirstChild)
{
DocType = document.DocumentType;
}
@@ -26,7 +25,7 @@ public HTMLTag Body
{
var source = GetSource();
- _body = source.FirstOrDefault(x => x.NameEqualsIgnoreCase("body"));
+ _body = source.OfType("body").IgnoreCase().FirstOrDefault();
_fetchedBody = true;
}
return _body;
@@ -42,7 +41,7 @@ public HTMLTag Head
if (!_fetchedHead)
{
var source = GetSource();
- _head = source.FirstOrDefault(x => x.NameEqualsIgnoreCase("head"));
+ _head = source.OfType("head").IgnoreCase().FirstOrDefault();
_fetchedHead = true;
}
return _head;
@@ -52,14 +51,10 @@ public HTMLTag Head
private IEnumerable<HTMLTag> GetSource()
{
IEnumerable<HTMLTag> source = new[] { this };
- if (this.NameEqualsIgnoreCase(DefaultName))
+ if (source.Count() == 1 &&
+ source.First().TypeEqualsIgnoreCase("html"))
{
- source = ChildTags;
- if (source.Count() == 1 &&
- source.First().NameEqualsIgnoreCase("html"))
- {
- source = source.First().ChildTags;
- }
+ source = source.First().ChildTags;
}
return source;
}
View
47 src/LinqToHtml/HTMLTag.cs
@@ -13,59 +13,70 @@ public HTMLTag(XmlNode node)
_node = node;
}
- public IEnumerable<HTMLTag> AllDescendantTags
+ public IEnumerable<HTMLTagAttribute> Attributes
{
get
{
- if (!_node.HasChildNodes)
+ if (_node.Attributes == null)
{
yield break;
}
- var xmlNodes = _node.ChildXmlNodes();
- var allXmlNodes = xmlNodes.Flatten();
-
- foreach (var tag in allXmlNodes.Select(item => new HTMLTag(item)))
+ foreach (var attribute in _node.Attributes
+ .Cast<XmlAttribute>()
+ .Select(x => new HTMLTagAttribute(x)))
{
- yield return tag;
+ yield return attribute;
}
}
}
- public IEnumerable<HTMLTagAttribute> Attributes
+
+ public IEnumerable<HTMLTag> ChildTags
{
get
{
- if (_node.Attributes == null)
+ if (!_node.HasChildNodes)
{
yield break;
}
-
- foreach (var attribute in _node.Attributes
- .Cast<XmlAttribute>()
- .Select(x => new HTMLTagAttribute(x)))
+ var childXmlNodes = _node.ChildXmlNodes();
+ foreach (var tag in childXmlNodes.Select(item => new HTMLTag(item)))
{
- yield return attribute;
+ yield return tag;
}
}
}
- public IEnumerable<HTMLTag> ChildTags
+ public string Content
+ {
+ get { return _node.InnerText; }
+ }
+
+ public IEnumerable<HTMLTag> DescendantTags
{
get
{
if (!_node.HasChildNodes)
{
yield break;
}
- var childXmlNodes = _node.ChildXmlNodes();
- foreach (var tag in childXmlNodes.Select(item => new HTMLTag(item)))
+
+ var xmlNodes = _node.ChildXmlNodes();
+ var allXmlNodes = xmlNodes.Flatten();
+
+ foreach (var tag in allXmlNodes.Select(item => new HTMLTag(item)))
{
yield return tag;
}
}
}
- public string Name
+ public HTMLTag Parent
+ {
+ get { return new HTMLTag(_node.ParentNode); }
+ }
+
+ public string Type
{
get { return _node.Name; }
}
View
2 src/LinqToHtml/HTMLTagAttributeExtensions.cs
@@ -6,7 +6,7 @@ public static class HTMLTagAttributeExtensions
{
public static bool NameEqualsIgnoreCase(this HTMLTagAttribute attribute, string name)
{
- return String.Compare(attribute.Name, name, true) == 0;
+ return String.Equals(attribute.Name, name, StringComparison.InvariantCultureIgnoreCase);
}
}
}
View
8 src/LinqToHtml/HTMLTagExtensions.cs
@@ -5,14 +5,14 @@ namespace LinqToHtml
{
public static class HTMLTagExtensions
{
- public static bool NameEqualsIgnoreCase(this HTMLTag htmlTag, string name)
+ public static bool HasAttribute(this HTMLTag htmlTag, Func<HTMLTagAttribute, bool> matchRule)
{
- return String.Compare(htmlTag.Name, name, true) == 0;
+ return htmlTag.Attributes.Any(matchRule);
}
- public static bool HasAttribute(this HTMLTag htmlTag, Func<HTMLTagAttribute, bool> matchRule)
+ public static bool TypeEqualsIgnoreCase(this HTMLTag htmlTag, string name)
{
- return htmlTag.Attributes.Any(matchRule);
+ return String.Equals(htmlTag.Type, name, StringComparison.InvariantCultureIgnoreCase);
}
}
}
View
38 src/LinqToHtml/HTMLTagTypeFilter.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace LinqToHtml
+{
+ public class HTMLTagTypeFilter : IEnumerable<HTMLTag>
+ {
+ private readonly IEnumerable<HTMLTag> _items;
+ private readonly string _type;
+ private StringComparison _stringComparison;
+
+ public HTMLTagTypeFilter(IEnumerable<HTMLTag> items, string type)
+ {
+ _items = items;
+ _type = type;
+ _stringComparison = StringComparison.InvariantCulture;
+ }
+
+ public IEnumerator<HTMLTag> GetEnumerator()
+ {
+ var htmlTags = _items.Where(x => String.Equals(x.Type, _type, _stringComparison));
+ return htmlTags.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public HTMLTagTypeFilter IgnoreCase()
+ {
+ _stringComparison = StringComparison.InvariantCultureIgnoreCase;
+ return this;
+ }
+ }
+}
View
12 src/LinqToHtml/IEnumerableHTMLTagExtensions.cs
@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+
+namespace LinqToHtml
+{
+ public static class IEnumerableHTMLTagExtensions
+ {
+ public static HTMLTagTypeFilter OfType(this IEnumerable<HTMLTag> items, string type)
+ {
+ return new HTMLTagTypeFilter(items, type);
+ }
+ }
+}
View
2 src/LinqToHtml/LinqToHtml.csproj
@@ -51,6 +51,8 @@
<Compile Include="HTMLTagAttribute.cs" />
<Compile Include="HTMLTagAttributeExtensions.cs" />
<Compile Include="HTMLTagExtensions.cs" />
+ <Compile Include="HTMLTagTypeFilter.cs" />
+ <Compile Include="IEnumerableHTMLTagExtensions.cs" />
<Compile Include="IEnumerableXmlNodeExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="XmlNodeListExtensions.cs" />

0 comments on commit 6fbff4b

Please sign in to comment.