I am very new to programming and my first task is to create a WCF service that will take an ATOM feed and expose it to my application. Now, I’ve read up on XML serialization and syndication but it doesn’t seem to be what I need in my (lack of) experience.
Here is a snippet of the feed. It’s generated by a seedlist spi
<atom:generator version="1.2" lconn:version="4.5.0.0">
Seedlist Service Backend System</atom:generator>
<wplc:timestamp isPartial="false">AAABQtdnfpE=</wplc:timestamp>
<atom:category term="ContentSourceType/Wikis" scheme="com.ibm.wplc.taxonomy://feature_taxonomy"
label="Wikis"/>
<atom:title>Wikis : 0 entries of Seedlist WIKIS</atom:title>
<atom:updated>2013-12-09T13:49:13+01:00</atom:updated>
Do I need to create objects for all these elements?
And what about these wplc elements?
<wplc:action do="update"/>
<wplc:fieldInfo id="FIELD_ENTRY_TYPE" name="item type"
description="item type - page, file or wiki" type="string"
contentSearchable="false" fieldSearchable="true"
parametric="false" returnable="true" sortable="false"
supportsExactMatch="false"/>
<wplc:fieldInfo id="FIELD_TAG" name="Tag"
description="Document tag" type="string"
contentSearchable="true" fieldSearchable="true"
parametric="false" returnable="true" sortable="false"
supportsExactMatch="true"/>
All the examples, tutorials and explanations I find are of simple xml files
So can I just use XML Reader to achieve this? And if so, I need some help.
Here is a sample WCF I found:
public class Service1 : IService1
{
public string GetData(string value)
{
WebRequest request = WebRequest.Create("http://wheremyxmlis/file.xml");
WebResponse response = request.GetResponse();
Stream dataStream = response.GetResponseStream();
XmlReader reader = XmlReader.Create("http://wheremyxmlis/file.xml");
reader = new XmlTextReader("http://wheremyxmlis.xml");
try
{
reader = new XmlTextReader("http://wheremyxmlis/file.xml");
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
Console.Write("<{0}>", reader.Name);
break;
case XmlNodeType.Text:
Console.Write(reader.Value);
break;
case XmlNodeType.CDATA:
Console.Write("<![CDATA[{0}]]>", reader.Value);
break;
case XmlNodeType.ProcessingInstruction:
Console.Write("<?{0} {1}?>", reader.Name, reader.Value);
break;
case XmlNodeType.Comment:
Console.Write("<!--{0}-->", reader.Value);
break;
case XmlNodeType.XmlDeclaration:
Console.Write("<?xml version='1.0'?>");
break;
case XmlNodeType.Document:
break;
case XmlNodeType.DocumentType:
Console.Write("<!DOCTYPE {0} [{1}]", reader.Name, reader.Value);
break;
case XmlNodeType.EntityReference:
Console.Write(reader.Name);
break;
case XmlNodeType.EndElement:
Console.Write("</{0}>", reader.Name);
break;
}
}
}
finally
{
if (reader != null)
reader.Close();
response.Close();
This is the solution I managed to come up with and it works!
This is just a class file added to the WCF Service library
public class Item
{
public string Link { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public string Author { get; set; }
public DateTime Updated { get; set; }
public string FeedType { get; set; }
public string Tag { get; set; }
public Item()
{
//Link = "";
//Title = "";
//Name = "";
//Content = "";
//Updated = DateTime.Today;
// FeedType = FeedType.RSS;
}
}
/// <summary>
/// A simple RSS, RDF and ATOM feed parser.
/// </summary>
public class FeedParser
{
/// <summary>
/// Parses the given <see cref="FeedType"/> and returns a <see cref="IList<Item>"/>.
/// </summary>
/// <returns></returns>
public IList<Item> Parse(XDocument doc, string feedType)
{
switch (feedType)
{
case "RSS":
return ParseRss(doc);
case "RDF":
return ParseRdf(doc);
case "Atom":
return ParseAtom(doc);
default:
throw new NotSupportedException(string.Format("{0} is not supported", feedType.ToString()));
}
}
/// <summary>
/// Parses an Atom feed and returns a <see cref="IList<Item>"/>.
/// </summary>
public virtual IList<Item> ParseAtom(XDocument doc)
{
try
{
// Feed/Entry
var entries = from item in doc.Root.Elements().Where(i => i.Name.LocalName == "entry")
select new Item
{
FeedType = "Atom",
Title = item.Elements().First(i => i.Name.LocalName == "title").Value,
Author = item.Elements().First(i => i.Name.LocalName == "author").Value, //must add child element "name"
Content = item.Elements().First(i => i.Name.LocalName == "summary").Value,
Tag = item.Elements().First(i => i.Name.LocalName == "field").Value, //must specify FIELD_TAG
Link = item.Elements().First(i => i.Name.LocalName == "link").Attribute("href").Value,
Updated = ParseDate(item.Elements().First(i => i.Name.LocalName == "updated").Value),
};
return entries.ToList();
}
catch (Exception ex)
{
return new List<Item>();
}
}
/// <summary>
/// Parses an RSS feed and returns a <see cref="IList<Item>"/>.
/// </summary>
public virtual IList<Item> ParseRss(XDocument doc)
{
try
{
// RSS/Channel/item
var entries = from item in doc.Root.Descendants().First(i => i.Name.LocalName == "channel").Elements().Where(i => i.Name.LocalName == "item")
select new Item
{
FeedType = "RSS",
Content = item.Elements().First(i => i.Name.LocalName == "description").Value,
Author = item.Elements().First(i => i.Name.LocalName == "name").Value, //Newly added
Link = item.Elements().First(i => i.Name.LocalName == "link href").Value,
Updated = DateTime.Parse(item.Elements().First(i => i.Name.LocalName == "updated").Value),
Title = item.Elements().First(i => i.Name.LocalName == "title").Value
};
return entries.ToList();
}
catch
{
return new List<Item>();
}
}
/// <summary>
/// Parses an RDF feed and returns a <see cref="IList<Item>"/>.
/// </summary>
public virtual IList<Item> ParseRdf(XDocument doc)
{
try
{
// <item> is under the root
var entries = from item in doc.Root.Descendants().Where(i => i.Name.LocalName == "item")
select new Item
{
FeedType = "RDF",
Content = item.Elements().First(i => i.Name.LocalName == "description").Value,
Author = item.Elements().First(i => i.Name.LocalName == "name").Value,
Link = item.Elements().First(i => i.Name.LocalName == "link href").Value,
Updated = DateTime.Parse(item.Elements().First(i => i.Name.LocalName == "updated").Value),
Title = item.Elements().First(i => i.Name.LocalName == "title").Value
};
return entries.ToList();
}
catch
{
return new List<Item>();
}
}
private DateTime ParseDate(string date)
{
DateTime result;
if (DateTime.TryParse(date, out result))
return result;
else
return DateTime.MinValue;
}
}
}
And here is the existing Service1.cs that I modified
public class Service1 : IService1
{
public IList<Item> GetData()
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("URL of the seedlist");
request.Method = "GET";
request.Accept = "application/atom+xml";
request.ContentType = "application/atom+xml;type=entry";
request.Credentials = new NetworkCredential("username", "password");
ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(ValidateServerCertificate);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
XDocument xDoc = XDocument.Load(new StreamReader(response.GetResponseStream()));
FeedParser parser = new FeedParser();
var items = parser.Parse(xDoc, "Atom");
return items;
}
//for testing purpose only, accept any dodgy certificate...
public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}
public Item GetItemByLink(string url)
{
var items = GetData();
foreach (var item in items)
{
if(item.Link == url)
{
return item;
}
}
return null;
}
}