Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

add explicit type conversion to HTMLTag; add test and fix for parsing…

… an XML document; add Resharper 5.0 codestyle
  • Loading branch information...
commit a44de71e7f4dc5b22460b7860b45819dc47e2f9d 1 parent a62ffad
@handcraftsman handcraftsman authored
View
6 src/LinqToHtml.5.0.ReSharper
@@ -0,0 +1,6 @@
+<Configuration>
+ <CodeStyleSettings>
+ <ExternalPath>D:\data\projects\csharp\lib\FluentAssert\src\ReSharper 5.0 Code Styles.xml</ExternalPath>
+ <Sharing>EXTERNAL</Sharing>
+ </CodeStyleSettings>
+</Configuration>
View
411 src/LinqToHtml.Tests/HTMLDocumentTests.cs
@@ -7,179 +7,240 @@
namespace LinqToHtml.Tests
{
- public class HTMLDocumentTests
- {
- [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_the_BODY_tag
- {
- private string _html;
- private HTMLTag _result;
-
- [Test]
- public void Given_an_html_document_that_has_a_child_BODY_tag()
- {
- Test.Verify(
- with_a_document_that_has_a_child_BODY_tag,
- when_asked_for_the_BODY_tag,
- should_not_return_null,
- should_return_the_BODY_tag
- );
- }
-
- [Test]
- public void Given_only_a_BODY_tag()
- {
- Test.Verify(
- with_only_a_BODY_tag,
- when_asked_for_the_BODY_tag,
- should_not_return_null,
- should_return_the_BODY_tag
- );
- }
-
- private void should_not_return_null()
- {
- _result.ShouldNotBeNull();
- }
-
- private void should_return_the_BODY_tag()
- {
- _result.TypeEqualsIgnoreCase("BODY").ShouldBeTrue();
- }
-
- private void when_asked_for_the_BODY_tag()
- {
- _result = HTMLParser.Parse(_html).Body;
- }
-
- private void with_a_document_that_has_a_child_BODY_tag()
- {
- _html = "<html><body></body></html>";
- }
-
- private void with_only_a_BODY_tag()
- {
- _html = "<body></body>";
- }
- }
-
- [TestFixture]
- public class When_asked_for_the_HEAD_tag
- {
- private string _html;
- private HTMLTag _result;
-
- [Test]
- public void Given_an_html_document_that_has_a_child_HEAD_tag()
- {
- Test.Verify(
- with_a_document_that_has_a_child_HEAD_tag,
- when_asked_for_the_HEAD_tag,
- should_not_return_null,
- should_return_the_HEAD_tag
- );
- }
-
- [Test]
- public void Given_only_a_HEAD_tag()
- {
- Test.Verify(
- with_only_a_HEAD_tag,
- when_asked_for_the_HEAD_tag,
- should_not_return_null,
- should_return_the_HEAD_tag
- );
- }
-
- private void should_not_return_null()
- {
- _result.ShouldNotBeNull();
- }
-
- private void should_return_the_HEAD_tag()
- {
- _result.TypeEqualsIgnoreCase("HEAD").ShouldBeTrue();
- }
-
- private void when_asked_for_the_HEAD_tag()
- {
- _result = HTMLParser.Parse(_html).Head;
- }
-
- private void with_a_document_that_has_a_child_HEAD_tag()
- {
- _html = "<html><head></head></html>";
- }
-
- private void with_only_a_HEAD_tag()
- {
- _html = "<head></head>";
- }
- }
- }
+ public class HTMLDocumentTests
+ {
+ public class Person
+ {
+ public int Age { get; set; }
+ public char Gender { get; set; }
+ public string Given { get; set; }
+ public string Surname { get; set; }
+
+ public override string ToString()
+ {
+ return Given + " " + Surname + " Age: " + Age + " Gender: " + Gender;
+ }
+ }
+
+ [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_the_BODY_tag
+ {
+ private string _html;
+ private HTMLTag _result;
+
+ [Test]
+ public void Given_an_html_document_that_has_a_child_BODY_tag()
+ {
+ Test.Verify(
+ with_a_document_that_has_a_child_BODY_tag,
+ when_asked_for_the_BODY_tag,
+ should_not_return_null,
+ should_return_the_BODY_tag
+ );
+ }
+
+ [Test]
+ public void Given_only_a_BODY_tag()
+ {
+ Test.Verify(
+ with_only_a_BODY_tag,
+ when_asked_for_the_BODY_tag,
+ should_not_return_null,
+ should_return_the_BODY_tag
+ );
+ }
+
+ private void should_not_return_null()
+ {
+ _result.ShouldNotBeNull();
+ }
+
+ private void should_return_the_BODY_tag()
+ {
+ _result.TypeEqualsIgnoreCase("BODY").ShouldBeTrue();
+ }
+
+ private void when_asked_for_the_BODY_tag()
+ {
+ _result = HTMLParser.Parse(_html).Body;
+ }
+
+ private void with_a_document_that_has_a_child_BODY_tag()
+ {
+ _html = "<html><body></body></html>";
+ }
+
+ private void with_only_a_BODY_tag()
+ {
+ _html = "<body></body>";
+ }
+ }
+
+ [TestFixture]
+ public class When_asked_for_the_HEAD_tag
+ {
+ private string _html;
+ private HTMLTag _result;
+
+ [Test]
+ public void Given_an_html_document_that_has_a_child_HEAD_tag()
+ {
+ Test.Verify(
+ with_a_document_that_has_a_child_HEAD_tag,
+ when_asked_for_the_HEAD_tag,
+ should_not_return_null,
+ should_return_the_HEAD_tag
+ );
+ }
+
+ [Test]
+ public void Given_only_a_HEAD_tag()
+ {
+ Test.Verify(
+ with_only_a_HEAD_tag,
+ when_asked_for_the_HEAD_tag,
+ should_not_return_null,
+ should_return_the_HEAD_tag
+ );
+ }
+
+ private void should_not_return_null()
+ {
+ _result.ShouldNotBeNull();
+ }
+
+ private void should_return_the_HEAD_tag()
+ {
+ _result.TypeEqualsIgnoreCase("HEAD").ShouldBeTrue();
+ }
+
+ private void when_asked_for_the_HEAD_tag()
+ {
+ _result = HTMLParser.Parse(_html).Head;
+ }
+
+ private void with_a_document_that_has_a_child_HEAD_tag()
+ {
+ _html = "<html><head></head></html>";
+ }
+
+ private void with_only_a_HEAD_tag()
+ {
+ _html = "<head></head>";
+ }
+ }
+
+ [TestFixture]
+ public class When_asked_to_parse_XML
+ {
+ [Test]
+ public void Should_parse_the_content_correctly()
+ {
+ const string html = @"<?xml version='1.0' encoding='utf-8' ?>
+<People>
+ <Person>
+ <FirstName>Plácido</FirstName>
+ <LastName>Domingo</LastName>
+ <Age>69</Age>
+ <Gender>M</Gender>
+ </Person>
+ <Person>
+ <FirstName>Enrico</FirstName>
+ <LastName>Caruso</LastName>
+ <Age>48</Age>
+ <Gender>M</Gender>
+ </Person>
+ <Person>
+ <FirstName>Μαρία</FirstName>
+ <LastName>Κάλλας</LastName>
+ <Age>53</Age>
+ <Gender>F</Gender>
+ </Person>
+</People>
+";
+ var doc = HTMLParser.Parse(html);
+ var persons = doc
+ .OfType("Person")
+ .Select(x => new Person
+ {
+ Given = (string)x["FirstName"],
+ Surname = (string)x["LastName"],
+ Age = (int)x["Age"],
+ Gender = (char)x["Gender"],
+ });
+
+ persons.Count().ShouldBeEqualTo(3, "found incorrect number of persons");
+ var kάλλας = persons.Last();
+ kάλλας.Age.ShouldBeEqualTo(53);
+ kάλλας.Gender.ShouldBeEqualTo('F');
+ kάλλας.Given.ShouldBeEqualTo("Μαρία");
+ kάλλας.Surname.ShouldBeEqualTo("Κάλλας");
+ }
+ }
+ }
}
View
2  src/LinqToHtml/HTMLDocument.cs
@@ -12,7 +12,7 @@ public class HTMLDocument : HTMLTag
private HTMLTag _head;
public HTMLDocument(XmlDocument document)
- : base(document.FirstChild)
+ : base(document.DocumentElement)
{
DocType = document.DocumentType;
}
View
295 src/LinqToHtml/HTMLTag.cs
@@ -1,124 +1,191 @@
-using System.Collections.Generic;
+using System;
+using System.Collections;
+using System.Collections.Generic;
using System.Linq;
using System.Xml;
namespace LinqToHtml
{
- public class HTMLTag
- {
- private readonly XmlNode _node;
-
- public HTMLTag(XmlNode node)
- {
- _node = node;
- }
-
- public IEnumerable<HTMLTagAttribute> Attributes
- {
- get
- {
- if (_node.Attributes == null)
- {
- yield break;
- }
-
- foreach (var attribute in _node.Attributes
- .Cast<XmlAttribute>()
- .Select(x => new HTMLTagAttribute(x)))
- {
- yield return attribute;
- }
- }
- }
-
- public IEnumerable<HTMLTag> ChildTags
- {
- get
- {
- if (!_node.HasChildNodes)
- {
- yield break;
- }
- var childXmlNodes = _node.ChildXmlNodes();
- foreach (var tag in childXmlNodes.Select(item => new HTMLTag(item)))
- {
- yield return tag;
- }
- }
- }
-
- public string Content
- {
- get { return _node.InnerText; }
- }
-
- public IEnumerable<HTMLTag> DescendantTags
- {
- get
- {
- if (!_node.HasChildNodes)
- {
- yield break;
- }
-
- var xmlNodes = _node.ChildXmlNodes();
- var allXmlNodes = xmlNodes.Flatten();
-
- foreach (var tag in allXmlNodes.Select(item => new HTMLTag(item)))
- {
- yield return tag;
- }
- }
- }
-
- public string this [string key]
- {
- get
- {
- var child = ChildTags.FirstOrDefault(x => x.Type == key);
+ public class HTMLTag : IEnumerable<HTMLTag>
+ {
+ private readonly XmlNode _node;
+
+ public HTMLTag(XmlNode node)
+ {
+ _node = node;
+ }
+
+ public IEnumerable<HTMLTagAttribute> Attributes
+ {
+ get
+ {
+ if (_node.Attributes == null)
+ {
+ yield break;
+ }
+
+ foreach (var attribute in _node.Attributes
+ .Cast<XmlAttribute>()
+ .Select(x => new HTMLTagAttribute(x)))
+ {
+ yield return attribute;
+ }
+ }
+ }
+
+ public IEnumerable<HTMLTag> ChildTags
+ {
+ get
+ {
+ if (!_node.HasChildNodes)
+ {
+ yield break;
+ }
+ var childXmlNodes = _node.ChildXmlNodes();
+ foreach (var tag in childXmlNodes.Select(item => new HTMLTag(item)))
+ {
+ yield return tag;
+ }
+ }
+ }
+
+ public string Content
+ {
+ get { return _node.InnerText; }
+ }
+
+ public IEnumerable<HTMLTag> DescendantTags
+ {
+ get
+ {
+ if (!_node.HasChildNodes)
+ {
+ yield break;
+ }
+
+ var xmlNodes = _node.ChildXmlNodes();
+ var allXmlNodes = xmlNodes.Flatten();
+
+ foreach (var tag in allXmlNodes.Select(item => new HTMLTag(item)))
+ {
+ yield return tag;
+ }
+ }
+ }
+
+ public HTMLTag this[string key]
+ {
+ get
+ {
+ var child = ChildTags.FirstOrDefault(x => x.Type == key);
if (child == null)
{
return null;
}
- return child.Content;
- }
- }
-
- public HTMLTag Parent
- {
- get { return new HTMLTag(_node.ParentNode); }
- }
-
- public string RawContent
- {
- get { return _node.InnerXml; }
- }
-
- public string Type
- {
- get { return _node.Name; }
- }
-
- public void MapTo<T>(T destination)
- {
- var properties = destination
- .GetType()
- .GetProperties()
- .Where(x => x.CanWrite)
- .ToDictionary(x => x.Name.ToLower());
-
- var attributes = Attributes
- .ToDictionary(x => x.Name.ToLower(), x => x.Value);
-
- var matches = attributes.Where(x => properties.ContainsKey(x.Key));
-
- foreach (var match in matches)
- {
- var property = properties[match.Key];
- PropertySetter
- .GetFor(property.PropertyType)
- .SetValue(destination, property, match.Value);
- }
- }
- }
+ return child;
+ }
+ }
+
+ public HTMLTag Parent
+ {
+ get { return new HTMLTag(_node.ParentNode); }
+ }
+
+ public string RawContent
+ {
+ get { return _node.InnerXml; }
+ }
+
+ public string Type
+ {
+ get { return _node.Name; }
+ }
+
+ public IEnumerator<HTMLTag> GetEnumerator()
+ {
+ return DescendantTags.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public void MapTo<T>(T destination)
+ {
+ var properties = destination
+ .GetType()
+ .GetProperties()
+ .Where(x => x.CanWrite)
+ .ToDictionary(x => x.Name.ToLower());
+
+ var attributes = Attributes
+ .ToDictionary(x => x.Name.ToLower(), x => x.Value);
+
+ var matches = attributes.Where(x => properties.ContainsKey(x.Key));
+
+ foreach (var match in matches)
+ {
+ var property = properties[match.Key];
+ PropertySetter
+ .GetFor(property.PropertyType)
+ .SetValue(destination, property, match.Value);
+ }
+ }
+
+ public static explicit operator int(HTMLTag htmlTag)
+ {
+ return Int32.Parse(htmlTag.Content);
+ }
+
+ public static explicit operator bool(HTMLTag htmlTag)
+ {
+ return Boolean.Parse(htmlTag.Content);
+ }
+
+ public static explicit operator double(HTMLTag htmlTag)
+ {
+ return Double.Parse(htmlTag.Content);
+ }
+
+ public static explicit operator decimal(HTMLTag htmlTag)
+ {
+ return Decimal.Parse(htmlTag.Content);
+ }
+
+ public static explicit operator float(HTMLTag htmlTag)
+ {
+ return Single.Parse(htmlTag.Content);
+ }
+
+ public static explicit operator long(HTMLTag htmlTag)
+ {
+ return Int64.Parse(htmlTag.Content);
+ }
+
+ public static explicit operator DateTime(HTMLTag htmlTag)
+ {
+ return DateTime.Parse(htmlTag.Content);
+ }
+
+ public static explicit operator char(HTMLTag htmlTag)
+ {
+ return Char.Parse(htmlTag.Content);
+ }
+
+ public static explicit operator short(HTMLTag htmlTag)
+ {
+ return Int16.Parse(htmlTag.Content);
+ }
+
+ public static explicit operator byte(HTMLTag htmlTag)
+ {
+ return Byte.Parse(htmlTag.Content);
+ }
+
+ public static explicit operator string(HTMLTag htmlTag)
+ {
+ return htmlTag.Content;
+ }
+ }
}
Please sign in to comment.
Something went wrong with that request. Please try again.