Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BasePropertyAttribute - Renamed NamespaceUrl to NamespaceUri. #4

Open
wants to merge 33 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
4bd3ff8
Version 1.0.0
dotnetgeek Aug 17, 2016
fd37f06
add documentation
dotnetgeek Aug 22, 2016
32bcaac
Update documentation
dotnetgeek Sep 17, 2016
5368328
fix: Missing entry element: author
dotnetgeek Sep 17, 2016
7234a14
fix Use of unknown namespace: None for tag rights
dotnetgeek Sep 17, 2016
173348a
Add Enclosure node to RSS
dotnetgeek Oct 23, 2017
af0d01b
Add Enclosure node to RSS
dotnetgeek Oct 23, 2017
a86ecb5
Merge
dotnetgeek Oct 23, 2017
975f92e
fix merge issue
dotnetgeek Oct 23, 2017
445d26a
Convert to NETSTANDARD lib
dotnetgeek Oct 26, 2017
9630ba4
Setup Travis build
dotnetgeek Oct 26, 2017
e482579
Add appveyor build description
dotnetgeek Oct 26, 2017
d65301c
add build worker image to appveyor.yml
dotnetgeek Oct 26, 2017
ae2fbd2
add xunit.runner.console
dotnetgeek Oct 26, 2017
2eb4da5
set timezone for tests
dotnetgeek Oct 26, 2017
7540d8d
configure nuget source as env
dotnetgeek Oct 26, 2017
f6cd4b0
Add build status information to readme
dotnetgeek Oct 27, 2017
6ef9f55
Add nuget and license badge
dotnetgeek Oct 27, 2017
a659267
add appveyor config for dev build
dotnetgeek Oct 30, 2017
5dab6f0
do not execute publish and push step for dev build
dotnetgeek Oct 30, 2017
e0f66e5
Update Cake build.ps1
dotnetgeek Oct 30, 2017
c967403
Revert "Update Cake build.ps1"
dotnetgeek Oct 30, 2017
9c81870
upload test results to AppVeyor for dev build
dotnetgeek Nov 1, 2017
a68a81a
add build badge (develop and master) to readme
dotnetgeek Nov 1, 2017
a20429a
add branch filter to appveyor (master and dev)
dotnetgeek Nov 1, 2017
dbf7c67
merge appveyor build files
dotnetgeek Nov 1, 2017
34e46f0
add for keyword for appveyor config file
dotnetgeek Nov 1, 2017
87a4a7e
Add new fields Images and Webmaster to RSS Feed
Nov 3, 2017
49a5c96
add logo to atom feed
Nov 3, 2017
2303929
merge master to development
Nov 3, 2017
6b5c6d6
Atom and Rss 2.0 Feed generation via Attributes (no hard coding).
Mar 7, 2018
789cbad
BasePropertyAttribute - Renamed NamespaceUrl to NamespaceUri.
Mar 9, 2018
ae45371
Merge branch 'develop' into develop
wdcossey Jun 1, 2018
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
8 changes: 4 additions & 4 deletions src/Attributes/BasePropertyAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ public abstract class BasePropertyAttribute : Attribute

public string Namespace { get; set; }

public Uri Url { get; private set; }
public Uri Uri { get; private set; }

public string AttributeName { get; set; }

public string NamespaceUrl
public string NamespaceUri
{
get => Url?.ToString();
set => Url = new Uri(value);
get => Uri?.ToString();
set => Uri = new Uri(value);
}

public Type Writer { get; set; }
Expand Down
17 changes: 17 additions & 0 deletions src/Attributes/XmlNamespaceAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;

namespace dng.Syndication.Attributes
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class XmlNamespaceAttribute : Attribute
{
public string Prefix { get; }
public Uri Uri { get; }

public XmlNamespaceAttribute(string prefix, string uri)
{
Prefix = prefix;
Uri = new Uri(uri);
}
}
}
6 changes: 2 additions & 4 deletions src/Feed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ namespace dng.Syndication
{
public class Feed : IFeed
{


/// <summary>
/// Name for the feed.
/// </summary>
Expand All @@ -29,8 +27,8 @@ public class Feed : IFeed
/// Defines the hyperlink to the channel
/// </summary>
[AtomProperty("id", Required = true)]
[AtomProperty("link", NamespaceUrl = Namespaces.AtomNamespace, Writer = typeof(AtomLinkElementWriter))]
[Rss20Property("link", NamespaceUrl = Namespaces.AtomNamespace, Writer = typeof(AtomLinkElementWriter))]
[AtomProperty("link", NamespaceUri = Namespaces.AtomNamespace, Writer = typeof(AtomLinkElementWriter))]
[Rss20Property("link", NamespaceUri = Namespaces.AtomNamespace, Writer = typeof(AtomLinkElementWriter))]
[Rss20Property("link", Required = true, Writer = typeof(Rcf3986UriElementFormatter))]
public Uri Link { get; set; }

Expand Down
7 changes: 6 additions & 1 deletion src/Generators/AtomGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml.Linq;
using dng.Syndication.Attributes;
using dng.Syndication.Enums;
Expand All @@ -18,6 +21,8 @@ public override string Process()

var rootElement = new XElement(atomNamespace + "feed");

AddFeedNamespaces(rootElement);

var declaration = new XDeclaration("1.0", Encoding.UTF8.HeaderName, null);

var doc = new XDocument(declaration, rootElement);
Expand Down
26 changes: 21 additions & 5 deletions src/Generators/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,30 @@ public override string ToString()

public abstract FeedType FeedType { get; }

protected virtual XElement ParseProperties<TObject>(TObject obj, XElement parentElement = null, XNamespace @namespace = null)
protected virtual void AddFeedNamespaces(XElement element)
{
var namespaceAttributes =
Feed.GetType().GetCustomAttributes(typeof(XmlNamespaceAttribute), false)
.Cast<XmlNamespaceAttribute>().ToList();

if (!namespaceAttributes.Any())
{
return;
}

foreach (var attribute in namespaceAttributes)
{
element.SetAttributeValue(XNamespace.Xmlns + attribute.Prefix, attribute.Uri);
}
}

protected virtual XElement ParseProperties<TObject>(TObject obj, XElement parentElement, XNamespace @namespace = null)
where TObject : class
{
return ParsePropertiesInternal(obj, (object) null, parentElement, @namespace);
}

internal XElement ParsePropertiesInternal<TObject, TParent>(TObject obj, TParent parentobj, XElement parentElement = null, XNamespace @namespace = null)
internal XElement ParsePropertiesInternal<TObject, TParent>(TObject obj, TParent parentobj, XElement parentElement, XNamespace @namespace = null)
where TObject : class
where TParent : class
{
Expand All @@ -52,7 +69,6 @@ internal XElement ParsePropertiesInternal<TObject, TParent>(TObject obj, TParent
property.GetCustomAttributes(typeof(TAttribute), false)
.Cast<TAttribute>().ToList();


if (!propertyAttributes.Any())
{
continue;
Expand Down Expand Up @@ -150,9 +166,9 @@ private static XName GetElementName(TAttribute attribute, XNamespace @namespace)
{
XName result = attribute.Name;

if (!string.IsNullOrWhiteSpace(attribute.NamespaceUrl))
if (!string.IsNullOrWhiteSpace(attribute.NamespaceUri))
{
result = XNamespace.Get(attribute.NamespaceUrl) + attribute.Name;
result = XNamespace.Get(attribute.NamespaceUri) + attribute.Name;
}
else if (@namespace != null)
{
Expand Down
2 changes: 2 additions & 0 deletions src/Generators/Rss20Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public override string Process()

rootElement.Add(new XAttribute(XNamespace.Xmlns + "atom", atomNamespace));

AddFeedNamespaces(rootElement);

var parentElement = new XElement("channel");

rootElement.Add(ParseProperties(Feed, parentElement));
Expand Down
76 changes: 76 additions & 0 deletions tests/AtomGeneratorTests.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using dng.Syndication.Attributes;
using dng.Syndication.Generators;
using dng.Syndication.Writers;
using Xunit;

namespace dng.Syndication.Tests
{
public class AtomGeneratorTests
{
private const string DOTNETGEEK_ATOM_NAMESPACE = "http://www.dotnetgeek.com/Atom/2018";

[XmlNamespace("dng", DOTNETGEEK_ATOM_NAMESPACE)]
private class CustomAtomFeed : Feed
{
[AtomProperty("property", NamespaceUri = DOTNETGEEK_ATOM_NAMESPACE)]
public string MyProperty { get; set; }
}

private Feed CreateSimpleFeed()
{
var feed = new Feed
Expand Down Expand Up @@ -38,6 +49,39 @@ private Feed CreateSimpleFeed()
}
};

return feed;
}

private CustomAtomFeed CreateCustomFeed()
{
var feed = new CustomAtomFeed
{
Title = FeedContent.Text("dotnetgeek feed"),
Author = new Author
{
Name = "Daniel",
Email = "[email protected]"
},
Copyright = "2016 @ www.dotnetgeek.com",
Description = FeedContent.Text("Dotnet relevant thinks"),
Generator = "dng.Syndication",
Language = CultureInfo.GetCultureInfo("de"),
UpdatedDate = new DateTime(2016, 08, 16),
Link = new Uri("http://www.dotnetgeek.de/rss"),
FeedEntries = new List<IFeedEntry>
{
new FeedEntry
{
Title = FeedContent.Plain("First Entry"),
Content = FeedContent.Plain("Content"),
Link = new Uri("http://www.dotnetgeek.com/first-entry"),
Summary = FeedContent.Plain("summary"),
PublishDate = new DateTime(2016, 08, 16),
Updated = new DateTime(2016, 08, 16),
}
},
MyProperty = "my_custom_atom_value"
};

return feed;
}
Expand Down Expand Up @@ -107,6 +151,38 @@ public void Create_a_simple_atom_feed_with_logo()

Assert.Equal(expected, feedXml);
}

[Fact]
public void Create_a_custom_atom_feed()
{
var atomGenerator = new AtomGenerator(CreateCustomFeed());
var feedXml = atomGenerator.Process();

const string expected = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<feed xmlns:dng=\"http://www.dotnetgeek.com/Atom/2018\" xmlns=\"http://www.w3.org/2005/Atom\">" +
"<title type=\"text\">dotnetgeek feed</title>" +
"<author><name>Daniel</name><email>[email protected]</email></author>" +
"<id>http://www.dotnetgeek.de/rss</id>" +
"<link rel=\"self\" type=\"application/rss+xml\" href=\"http://www.dotnetgeek.de/rss\" />" +
"<updated>2016-08-16T00:00:00Z</updated>" +
"<rights>2016 @ www.dotnetgeek.com</rights>" +
"<generator>dng.Syndication</generator>" +
"<subtitle type=\"text\">Dotnet relevant thinks</subtitle>" +
"<entry>" +
"<title>First Entry</title>" +
"<link href=\"http://www.dotnetgeek.com/first-entry\" />" +
"<id>http://www.dotnetgeek.com/first-entry</id>" +
"<summary>summary</summary>" +
"<content>Content</content>" +
"<author><name>Daniel</name><email>[email protected]</email></author>" +
"<published>2016-08-16T00:00:00Z</published>" +
"<updated>2016-08-16T00:00:00Z</updated>" +
"</entry>" +
"<dng:property>my_custom_atom_value</dng:property>" +
"</feed>";

Assert.Equal(expected, feedXml);
}
}
}

70 changes: 68 additions & 2 deletions tests/Rss20GeneratorTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using dng.Syndication.Attributes;
using dng.Syndication.Generators;
using Xunit;

Expand All @@ -10,6 +11,15 @@ public class Rss20GeneratorTests
{
private readonly string _dateTimeOffset = new DateTime(2016, 08, 16).ToString("zzzz").Replace(":", "");

private const string DOTNETGEEK_RSS_NAMESPACE = "http://www.dotnetgeek.com/Rss/2018";

[XmlNamespace("dng", DOTNETGEEK_RSS_NAMESPACE)]
private class CustomRssFeed : Feed
{
[Rss20Property("property", NamespaceUri = DOTNETGEEK_RSS_NAMESPACE)]
public string MyProperty { get; set; }
}

private Feed CreateSimpleFeed()
{
var feed = new Feed
Expand All @@ -36,6 +46,35 @@ private Feed CreateSimpleFeed()
}
};

return feed;
}

private CustomRssFeed CreateCustomFeed()
{
var feed = new CustomRssFeed
{
Title = FeedContent.Plain("dotnetgeek feed"),
Author = new Author("Daniel", "[email protected]"),
Copyright = "2016 @ www.dotnetgeek.com",
Description = FeedContent.Plain("Dotnet relevant topics"),
Generator = "dng.Syndication",
Language = CultureInfo.GetCultureInfo("de"),
UpdatedDate = new DateTime(2016, 08, 16),
Link = new Uri("http://www.dotnetgeek.de/rss"),
FeedEntries = new List<IFeedEntry>
{
new FeedEntry
{
Title = FeedContent.Plain("First Entry"),
Content = FeedContent.Plain("Content"),
Link = new Uri("http://www.dotnetgeek.com/first-entry"),
Summary = FeedContent.Plain("summary"),
PublishDate = new DateTime(2016, 08, 16),
Updated = new DateTime(2016, 08, 16)
}
},
MyProperty = "my_custom_rss_value"
};

return feed;
}
Expand Down Expand Up @@ -103,8 +142,35 @@ public void Create_a_feed_with_image()

Assert.Equal(expected, feedXml);
}



[Fact]
public void Create_a_custom_feed()
{
var rss20Generator = new Rss20Generator(CreateCustomFeed());
var feedXml = rss20Generator.Process();

var expected = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\" xmlns:dng=\"http://www.dotnetgeek.com/Rss/2018\">" +
"<channel><title>dotnetgeek feed</title>" +
"<atom:link rel=\"self\" type=\"application/rss+xml\" href=\"http://www.dotnetgeek.de/rss\" />" +
"<link>http://www.dotnetgeek.de/rss</link>" +
$"<lastBuildDate>Tue, 16 Aug 2016 00:00:00 {_dateTimeOffset}</lastBuildDate>" +
"<language>de</language>" +
"<copyright>2016 @ www.dotnetgeek.com</copyright>" +
"<generator>dng.Syndication</generator>" +
"<description>Dotnet relevant topics</description>" +
"<item>" +
"<title>First Entry</title>" +
"<guid>http://www.dotnetgeek.com/first-entry</guid>" +
"<link>http://www.dotnetgeek.com/first-entry</link>" +
"<description>Content</description>" +
$"<pubDate>Tue, 16 Aug 2016 00:00:00 {_dateTimeOffset}</pubDate>" +
"</item>" +
"<dng:property>my_custom_rss_value</dng:property>" +
"</channel></rss>";

Assert.Equal(expected, feedXml);
}
}
}