For this project your task is to update the RSS Reader program you wrote for the previous
project so that it reads multiple RSS feeds and generates the same nicely formatted HTML page
of links for each feed, plus an HTML index page with links to the individual feed pages.
Your new program should ask the user for the name of an XML file containing a list of URLs for
RSS v2.0 feeds (see below for the format of this file) and for the name of an output file in which
to generate an HTML page with links to the pages for the individual RSS feeds (see below for an
example). It should then read the input XML file into an XMLTree object and then process the
list of RSS feeds from the XMLTree. For each RSS feed, the program should generate an HTML
page with a table of links to all the news items in the feed (just like in the previous project). The
program should also generate an HTML page with an index of links to the individual feed pages.
Format of the Input XML Document
The input XML document is pretty simple. This is the general structure:
1
2
3
4
5
6
...
The top-level tag, , has a required attribute, title, whose value is the title to be used in the index
page; nested inside the top-level tag are 1 or more tags with the following required attributes:
url, the URL of the RSS feed, name, the name to use for the link to the feed in the index page,
and file, the name of the HTML file in which to generate the feed\'s table of links to news items
(with the same format as the output in the previous project).
Here is an example of a valid XML input file.
Format of the HTML Output Index Page
The HTML index page should include the following information:
the title as the page title
a header with the page title inside
an unordered list where each item is the name of a feed linked to the feed URL
You can see an example of the index output here.
Method
Create a new Eclipse project by copying your RSSReader project and name the new project
RSSAggregator.
Open the src folder of this project and then open (default package). Rename the RSSReader.java
file to RSSAggregator.java. Open the RSSAggregator.java file in the editor.
Edit RSSAggregator.java to satisfy the problem requirements stated above. You should factor
out the code in your previous project that processed the RSS feed into the following separate
static method:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* Processes one XML RSS (version 2.0) feed from a given URL converting it
* into the corresponding HTML output file.
*
* @param url
* the URL of the RSS feed
* @param file
* the name of the HTML output file
* @param out
* the output stream to report progress or errors
* @updates out.content
* @requires out.is_open
* @ensures
* [reads RSS feed from url, saves HTML document with table of news items
* to file, appends to out.content any needed messages]
*
*/
private static void processFeed(String url, String file, SimpleWriter out) {...}
1
2
3
4
5
6
...
Solution
import components.simplereader.SimpleRead.
For this project your task is to update the RSS Reader program you w.pdf
1. For this project your task is to update the RSS Reader program you wrote for the previous
project so that it reads multiple RSS feeds and generates the same nicely formatted HTML page
of links for each feed, plus an HTML index page with links to the individual feed pages.
Your new program should ask the user for the name of an XML file containing a list of URLs for
RSS v2.0 feeds (see below for the format of this file) and for the name of an output file in which
to generate an HTML page with links to the pages for the individual RSS feeds (see below for an
example). It should then read the input XML file into an XMLTree object and then process the
list of RSS feeds from the XMLTree. For each RSS feed, the program should generate an HTML
page with a table of links to all the news items in the feed (just like in the previous project). The
program should also generate an HTML page with an index of links to the individual feed pages.
Format of the Input XML Document
The input XML document is pretty simple. This is the general structure:
1
2
3
4
5
6
...
The top-level tag, , has a required attribute, title, whose value is the title to be used in the index
page; nested inside the top-level tag are 1 or more tags with the following required attributes:
url, the URL of the RSS feed, name, the name to use for the link to the feed in the index page,
and file, the name of the HTML file in which to generate the feed's table of links to news items
(with the same format as the output in the previous project).
Here is an example of a valid XML input file.
Format of the HTML Output Index Page
The HTML index page should include the following information:
the title as the page title
a header with the page title inside
an unordered list where each item is the name of a feed linked to the feed URL
You can see an example of the index output here.
Method
Create a new Eclipse project by copying your RSSReader project and name the new project
2. RSSAggregator.
Open the src folder of this project and then open (default package). Rename the RSSReader.java
file to RSSAggregator.java. Open the RSSAggregator.java file in the editor.
Edit RSSAggregator.java to satisfy the problem requirements stated above. You should factor
out the code in your previous project that processed the RSS feed into the following separate
static method:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* Processes one XML RSS (version 2.0) feed from a given URL converting it
* into the corresponding HTML output file.
*
* @param url
* the URL of the RSS feed
* @param file
* the name of the HTML output file
* @param out
* the output stream to report progress or errors
* @updates out.content
* @requires out.is_open
3. * @ensures
* [reads RSS feed from url, saves HTML document with table of news items
* to file, appends to out.content any needed messages]
*
*/
private static void processFeed(String url, String file, SimpleWriter out) {...}
1
2
3
4
5
6
...
Solution
import components.simplereader.SimpleReader;
import components.simplereader.SimpleReader1L;
import components.simplewriter.SimpleWriter;
import components.simplewriter.SimpleWriter1L;
import components.xmltree.XMLTree;
import components.xmltree.XMLTree1;
public final class RSSAggregator {
/**
* Private constructor so this utility class cannot be instantiated.
*/
private RSSAggregator() {
}
/**
* Outputs the "opening" tags in the generated HTML file. These are the
* expected elements generated by this method:
*
* the channel tag title as the page
* title
* the page title inside a link to the link
4. *
*
* the channel description
*
*
*
* Date
* Source
* News
*
*
* @param channel
* the channel element XMLTree
* @param out
* the output stream
* @updates out.content
* @requires [the root of channel is a tag] and out.is_open
* @ensures out.content = #out.content * [the HTML "opening" tags]
*/
private static void outputHeader(XMLTree channel, SimpleWriter out) {
assert channel != null : "Violation of: channel is not null";
assert out != null : "Violation of: out is not null";
assert channel.isTag() && channel.label().equals("channel") : ""
+ "Violation of: the label root of channel is a tag";
assert out.isOpen() : "Violation of: out.is_open";
// Initial title as Empty Title, initial description as No description
String title = "Empty Title";
String description = "No description available";
String link;
// Retrieve the index of each tag
int indexTitle = getChildElement(channel, "title");
int indexDescription = getChildElement(channel, "description");
int indexLink = getChildElement(channel, "link");
// Check if title is empty
if (channel.child(indexTitle).numberOfChildren() > 0) {
5. title = channel.child(indexTitle).child(0).label();
}
// Check if description is empty
if (channel.child(indexDescription).numberOfChildren() > 0) {
description = channel.child(indexDescription).child(0).label();
}
link = channel.child(indexLink).child(0).label();
// Print opening
out.print(" " + " " + "t" + title + " "
+ " " + " " + "t " + "tt" + title + " " + "t " + "t
"
+ description + " "
+ " " + "t "
+ "ttDate " + "ttSource "
+ "ttNews " + "t ");
}
/**
* Outputs the "closing" tags in the generated HTML file. These are the
* expected elements generated by this method:
*
*
*
*
* @param out
* the output stream
* @updates out.contents
* @requires out.is_open
* @ensures out.content = #out.content * [the HTML "closing" tags]
*/
private static void outputFooter(SimpleWriter out) {
assert out != null : "Violation of: out is not null";
assert out.isOpen() : "Violation of: out.is_open";
// Print footer
out.println("t " + " " + "");
}
/**
6. * Finds the first occurrence of the given tag among the children of the
* given {@code XMLTree} and return its index; returns -1 if not found.
*
* @param xml
* the {@code XMLTree} to search
* @param tag
* the tag to look for
* @return the index of the first child of type tag of the {@code XMLTree}
* or -1 if not found
* @requires [the label of the root of xml is a tag]
* @ensures
*
*
* getChildElement =
* [the index of the first child of type tag of the {@code XMLTree} or
* -1 if not found]
*
*/
private static int getChildElement(XMLTree xml, String tag) {
assert xml != null : "Violation of: xml is not null";
assert tag != null : "Violation of: tag is not null";
assert xml.isTag() : "Violation of: the label root of xml is a tag";
int index = -1;
// Using while loop to search the index
int i = 0;
while (i < xml.numberOfChildren() && index == -1) {
if (xml.child(i).label().equals(tag)) {
// Retrieve the index
index = i;
}
i++;
}
return index;
}
/**
* Processes one news item and outputs one table row. The row contains three
7. * elements: the publication date, the source, and the title (or
* description) of the item.
*
* @param item
* the news item
* @param out
* the output stream
* @updates out.content
* @requires
*
*
* [the label of the root of item is an tag] and out.is_open
*
*
* @ensures
*
*
* out.content = #out.content *
* [an HTML table row with publication date, source, and title of news item]
*
*/
private static void processItem(XMLTree item, SimpleWriter out) {
assert item != null : "Violation of: item is not null";
assert out != null : "Violation of: out is not null";
assert item.isTag() && item.label().equals("item") : ""
+ "Violation of: the label root of item is an tag";
assert out.isOpen() : "Violation of: out.is_open";
String link = "";
String sourceLink = "";
String pubDate = "No date available";
String source = "No source available";
String title = "No title avaialble";
// Retrieve the index of each tag
int indexPubDate = getChildElement(item, "pubDate");
int indexSource = getChildElement(item, "source");
int indexTitle = getChildElement(item, "title");
8. int indexLink = getChildElement(item, "link");
// Check if item has pubdate
if (indexPubDate != -1) {
// Check if pubdate is empty
if (item.child(indexPubDate).numberOfChildren() != 0) {
pubDate = item.child(indexPubDate).child(0).label();
}
}
// Check if item has source
if (indexSource != -1) {
source = item.child(indexSource).child(0).label();
sourceLink = item.child(indexSource).attributeValue("url");
}
// Check if item has title
if (item.child(indexTitle).numberOfChildren() != 0) {
title = item.child(indexTitle).child(0).label();
}
// Check if item has link
if (indexLink != -1) {
// Check if link is empty
if (item.child(indexLink).numberOfChildren() != 0) {
link = item.child(indexLink).child(0).label();
// Check if sourceLink is empty
if (sourceLink.length() != 0) {
// Print out table elements
out.println(" " + "t" + pubDate + " "
+ "t" + "t"
+ source + " " + " " + "t "
+ "tt" + title + " "
+ "t " + "");
} else {
// Print out table elements
out.println(" " + "t" + pubDate + " "
+ "t" + source + " " + "t "
+ "tt" + title + " "
+ "t " + "");
9. }
} else {
// Check if sourceLink is empty
if (sourceLink.length() != 0) {
// Print out table elements
out.println(" " + "t" + pubDate + " "
+ "t" + "t"
+ source + " " + " " + "t " + title
+ "t " + "");
} else {
// Print out table elements
out.println(" " + "t" + pubDate + " "
+ "t" + source + " " + "t " + title
+ "t " + "");
}
}
}
}
/**
* Processes one XML RSS (version 2.0) feed from a given URL converting it
* into the corresponding HTML output file.
*
* @param url
* the URL of the RSS feed
* @param file
* the name of the HTML output file
* @param out
* the output stream to report progress or errors
* @updates out.content
* @requires out.is_open
* @ensures
*
*
* [reads RSS feed from url, saves HTML document with table of news items
* to file, appends to out.content any needed messages]
*
10. */
private static void processFeed(String url, String file, SimpleWriter out) {
// Output it into a html file
SimpleWriter fileOut = new SimpleWriter1L(file);
XMLTree root = new XMLTree1(url);
if (root.label().equals("rss")) {
// Check if version is 2.0
if (root.hasAttribute("version")) {
if (root.attributeValue("version").equals("2.0")) {
XMLTree channel = root.child(0);
// Generate the formatted page
outputHeader(channel, fileOut);
for (int i = 0; i < channel.numberOfChildren(); i++) {
if (channel.child(i).label().equals("item")) {
processItem(channel.child(i), fileOut);
}
}
outputFooter(fileOut);
}
}
} else {
out.println("Wrong file");
}
}
/**
* Main method.
*
* @param args
* the command line arguments; unused here
*/
public static void main(String[] args) {
SimpleReader in = new SimpleReader1L();
SimpleWriter out = new SimpleWriter1L();
// Ask for the index xml
out.println("Please enter an index xml: ");
String url0 = in.nextLine();
11. // Output it into a html file
SimpleWriter fileOut = new SimpleWriter1L("index.html");
XMLTree index = new XMLTree1(url0);
// Use a for loop to generate html pages of it
for (int i = 0; i < index.numberOfChildren(); i++) {
String fileName = index.child(i).attributeValue("file");
String urlName = index.child(i).attributeValue("url");
processFeed(urlName, fileName, out);
}
// Get the title name
String title = index.attributeValue("title");
// Print the index page
fileOut.print(" " + " " + "t" + title
+ " " + " " + " " + " "
+ "t " + title + "t " + " " + "t ");
for (int j = 0; j < index.numberOfChildren(); j++) {
String name = index.child(j).attributeValue("name");
String fileName = index.child(j).attributeValue("file");
fileOut.print("t " + "t
" + "tt" + name + " " + "t " + "t ");
}
fileOut.print("t " + " " + "");
in.close();
out.close();
fileOut.close();
}
}
feeds.xml