package net.hkionline.rss;
/* This is a XML writer intended to write RSS-feeds.
* Again I must thank Lars Vogel and his well written guide on the matter.
* The comments should explain what happens and where it happens.
*/
import java.io.FileOutputStream;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartDocument;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
public class Writer {
// The feed data model and the name of the feed file
String feedFile;
Channel feed;
public Writer(Channel feed, String feedFile){
this.feed = feed;
this.feedFile = feedFile;
}
public void write() throws Exception{
// Like in reading, we first create the factory objects and the actual writers first
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
FileOutputStream outputStream = new FileOutputStream(feedFile);
XMLEventWriter eventWriter = outputFactory.createXMLEventWriter(outputStream);
XMLEventFactory eventFactory = XMLEventFactory.newInstance();
// Now we create the document basic structure and the opening tags
XMLEvent newline = eventFactory.createDTD("\n");
// Create the XML document
StartDocument startDocument = eventFactory.createStartDocument();
eventWriter.add(startDocument);
eventWriter.add(newline);
// Create the rss-tag
StartElement rssBaseElement = eventFactory.createStartElement("", "", "rss");
eventWriter.add(rssBaseElement);
eventWriter.add(eventFactory.createAttribute("version", "2.0"));
eventWriter.add(newline);
// Create the channel-tag
eventWriter.add(eventFactory.createStartElement("", "", "channel"));
eventWriter.add(newline);
// Then we create and write the metadata/header tags
setElementData(eventWriter, "title", feed.getTitle());
setElementData(eventWriter, "description", feed.getDescription());
setElementData(eventWriter, "link", feed.getLink());
setElementData(eventWriter, "language", feed.getLanguage());
setElementData(eventWriter, "copyright", feed.getCopyright());
setElementData(eventWriter, "managingEditor", feed.getManagingEditor());
setElementData(eventWriter, "webmaster", feed.getWebmaster());
setElementData(eventWriter, "pubDate", feed.getPubDate());
setElementData(eventWriter, "lastBuildDate", feed.getLastBuildDate());
setElementData(eventWriter, "category", feed.getCategory());
setElementData(eventWriter, "generator", feed.getGenerator());
setElementData(eventWriter, "ttl", feed.getTtl());
setElementData(eventWriter, "image", feed.getImage());
// And finally we create and write the actual channel/feed items
for (Item item : feed.getItems()) {
//Open element with item tag
eventWriter.add(eventFactory.createStartElement("", "", "item"));
eventWriter.add(newline);
// Add the appropriate child elements
// TODO: Add only the elements that have data
setElementData(eventWriter, "title", item.getTitle());
setElementData(eventWriter, "description", item.getDescription());
setElementData(eventWriter, "link", item.getLink());
setElementData(eventWriter, "author", item.getAuthor());
setElementData(eventWriter, "category", item.getCategory());
setElementData(eventWriter, "enclosure", item.getEnclosure());
setElementData(eventWriter, "guid", item.getGuid());
setElementData(eventWriter, "pubDate", item.getPubDate());
setElementData(eventWriter, "source", item.getSource());
//Close the element
eventWriter.add(eventFactory.createEndElement("", "", "item"));
eventWriter.add(newline);
}
// Close the feed starting tags
eventWriter.add(eventFactory.createEndElement("", "", "channel"));
eventWriter.add(newline);
eventWriter.add(eventFactory.createEndElement("", "", "rss"));
eventWriter.add(newline);
// End the document and close the stream
eventWriter.add(eventFactory.createEndDocument());
eventWriter.close();
}
/*
* The reader had a getElementData to get individual element data, this is the comparable method for writing an individual element's data.
* The writer throws exception also so it is the responsibility of the caller of this Writer class to handle the exception.
*/
private void setElementData(XMLEventWriter eventWriter, String elementName, String elementValue) throws XMLStreamException{
// Create the factory object and some helpers to keep the feed nice looking
XMLEventFactory eventFactory = XMLEventFactory.newInstance();
XMLEvent newline = eventFactory.createDTD("\n");
XMLEvent tab = eventFactory.createDTD("\t");
// Create opening tag for the element
StartElement startElement = eventFactory.createStartElement("", "", elementName);
eventWriter.add(tab);
eventWriter.add(startElement);
// Add the element data string
Characters characters = eventFactory.createCharacters(elementValue);
eventWriter.add(characters);
// Close the element
EndElement eElement = eventFactory.createEndElement("", "", elementName);
eventWriter.add(eElement);
eventWriter.add(newline);
}
}