RSS Feeds with Java. This tutorial explains how to read and create RSS feeds with Java. Eclipse is used as the Java IDE and Java 25 is used.

1. RSS - Really Simple Syndication

An RSS document is an XML file that can be used to publish blog entries and news. The format of the XML file is specified via the RSS specification.

RSS stands for Really Simple Syndication (in version 2.0 of the RSS specification).

Typically a RSS file is provided by a web server, which RSS client read. These RSS clients parse the file and display it.

2. Prerequisites

As an RSS feed is a XML file we can use the Java XML parsers to read and create RSS feeds. The following will use the Java Stax XML parser.

For an introduction into XML and its usage with Java see Java XML Tutorial.

3. Project and Domain model

Create the Java project called de.vogella.rss. Create the following Java records, which are used as the domain model. Records are immutable data classes which automatically provide accessor methods, equals(), hashCode() and toString() implementations.

package de.vogella.rss.model;

/*
 * Represents one RSS message
 */
public record FeedMessage(String title, String description, String link, String author, String guid) {
}
package de.vogella.rss.model;

import java.util.List;

/*
 * Stores an RSS feed with its messages
 */
public record Feed(String title, String link, String description, String language, String copyright, String pubDate,
        List<FeedMessage> messages) {
}

4. Read RSS Feeds with Stax

4.1. Create the XML Reader class

Create the following class to read the XML file. It uses the java.net.URI API to create the URL and a switch expression with arrow syntax to process the XML elements.

package de.vogella.rss.read;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;

import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.XMLEvent;

import de.vogella.rss.model.Feed;
import de.vogella.rss.model.FeedMessage;

public class RSSFeedParser {
    static final String TITLE = "title";
    static final String DESCRIPTION = "description";
    static final String CHANNEL = "channel";
    static final String LANGUAGE = "language";
    static final String COPYRIGHT = "copyright";
    static final String LINK = "link";
    static final String AUTHOR = "author";
    static final String ITEM = "item";
    static final String PUB_DATE = "pubDate";
    static final String GUID = "guid";

    private final URL url;

    public RSSFeedParser(String feedUrl) {
        try {
            this.url = URI.create(feedUrl).toURL();
        } catch (MalformedURLException e) {
            throw new IllegalArgumentException(e);
        }
    }

    public Feed readFeed() {
        Feed feed = null;
        try (InputStream in = url.openStream()) {
            boolean isFeedHeader = true;
            // Set header values initially to the empty string
            String description = "";
            String title = "";
            String link = "";
            String language = "";
            String copyright = "";
            String author = "";
            String pubdate = "";
            String guid = "";

            // First create a new XMLInputFactory
            XMLInputFactory inputFactory = XMLInputFactory.newInstance();
            // create a new eventReader
            XMLEventReader eventReader = inputFactory.createXMLEventReader(in);
            // read the XML document
            while (eventReader.hasNext()) {
                XMLEvent event = eventReader.nextEvent();
                if (event.isStartElement()) {
                    String localPart = event.asStartElement().getName().getLocalPart();
                    switch (localPart) {
                    case ITEM -> {
                        if (isFeedHeader) {
                            isFeedHeader = false;
                            feed = new Feed(title, link, description, language, copyright, pubdate, new ArrayList<>());
                        }
                    }
                    case TITLE -> title = getCharacterData(eventReader);
                    case DESCRIPTION -> description = getCharacterData(eventReader);
                    case LINK -> link = getCharacterData(eventReader);
                    case GUID -> guid = getCharacterData(eventReader);
                    case LANGUAGE -> language = getCharacterData(eventReader);
                    case AUTHOR -> author = getCharacterData(eventReader);
                    case PUB_DATE -> pubdate = getCharacterData(eventReader);
                    case COPYRIGHT -> copyright = getCharacterData(eventReader);
                    default -> {
                        // ignore other elements
                    }
                    }
                } else if (event.isEndElement()) {
                    if (ITEM.equals(event.asEndElement().getName().getLocalPart())) {
                        FeedMessage message = new FeedMessage(title, description, link, author, guid);
                        feed.messages().add(message);
                        // reset the values so that they do not carry over to the next item
                        title = "";
                        description = "";
                        link = "";
                        author = "";
                        guid = "";
                    }
                }
            }
        } catch (XMLStreamException | IOException e) {
            throw new RuntimeException(e);
        }
        return feed;
    }

    private String getCharacterData(XMLEventReader eventReader) throws XMLStreamException {
        String result = "";
        XMLEvent event = eventReader.nextEvent();
        if (event instanceof Characters characters) {
            result = characters.getData();
        }
        return result;
    }
}

4.2. Test the code

The following uses a main method to test. You could also use JUnit.

package de.vogella.rss.tests;

import de.vogella.rss.model.Feed;
import de.vogella.rss.model.FeedMessage;
import de.vogella.rss.read.RSSFeedParser;

public class ReadTest {
    public static void main(String[] args) {
        RSSFeedParser parser = new RSSFeedParser("https://www.vogella.com/article.rss");
        Feed feed = parser.readFeed();
        System.out.println(feed);
        for (FeedMessage message : feed.messages()) {
            System.out.println(message);
        }
    }
}

5. Write RSS Feeds with Stax

5.1. Create writer

Create the following class to write the XML file. It uses try-with-resources to ensure that the output stream is closed.

package de.vogella.rss.write;

import java.io.FileOutputStream;
import java.io.IOException;

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;

import de.vogella.rss.model.Feed;
import de.vogella.rss.model.FeedMessage;

public class RSSFeedWriter {

    private final Feed rssfeed;
    private final String outputFile;

    public RSSFeedWriter(Feed rssfeed, String outputFile) {
        this.rssfeed = rssfeed;
        this.outputFile = outputFile;
    }

    public void write() throws IOException, XMLStreamException {

        // create a XMLOutputFactory
        XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();

        try (FileOutputStream out = new FileOutputStream(outputFile)) {

            // create XMLEventWriter
            XMLEventWriter eventWriter = outputFactory.createXMLEventWriter(out);

            // create a EventFactory
            XMLEventFactory eventFactory = XMLEventFactory.newInstance();
            XMLEvent end = eventFactory.createDTD("\n");

            // create and write Start Tag
            StartDocument startDocument = eventFactory.createStartDocument();
            eventWriter.add(startDocument);

            // create open tag
            eventWriter.add(end);

            StartElement rssStart = eventFactory.createStartElement("", "", "rss");
            eventWriter.add(rssStart);
            eventWriter.add(eventFactory.createAttribute("version", "2.0"));
            eventWriter.add(end);

            eventWriter.add(eventFactory.createStartElement("", "", "channel"));
            eventWriter.add(end);

            // Write the different nodes
            createNode(eventWriter, "title", rssfeed.title());
            createNode(eventWriter, "link", rssfeed.link());
            createNode(eventWriter, "description", rssfeed.description());
            createNode(eventWriter, "language", rssfeed.language());
            createNode(eventWriter, "copyright", rssfeed.copyright());
            createNode(eventWriter, "pubDate", rssfeed.pubDate());

            for (FeedMessage entry : rssfeed.messages()) {
                eventWriter.add(eventFactory.createStartElement("", "", "item"));
                eventWriter.add(end);
                createNode(eventWriter, "title", entry.title());
                createNode(eventWriter, "description", entry.description());
                createNode(eventWriter, "link", entry.link());
                createNode(eventWriter, "author", entry.author());
                createNode(eventWriter, "guid", entry.guid());
                eventWriter.add(end);
                eventWriter.add(eventFactory.createEndElement("", "", "item"));
                eventWriter.add(end);
            }

            eventWriter.add(end);
            eventWriter.add(eventFactory.createEndElement("", "", "channel"));
            eventWriter.add(end);
            eventWriter.add(eventFactory.createEndElement("", "", "rss"));
            eventWriter.add(end);

            eventWriter.add(eventFactory.createEndDocument());

            eventWriter.close();
        }
    }

    private void createNode(XMLEventWriter eventWriter, String name, String value) throws XMLStreamException {
        XMLEventFactory eventFactory = XMLEventFactory.newInstance();
        XMLEvent end = eventFactory.createDTD("\n");
        XMLEvent tab = eventFactory.createDTD("\t");
        // create Start node
        StartElement sElement = eventFactory.createStartElement("", "", name);
        eventWriter.add(tab);
        eventWriter.add(sElement);
        // create Content
        Characters characters = eventFactory.createCharacters(value);
        eventWriter.add(characters);
        // create End node
        EndElement eElement = eventFactory.createEndElement("", "", name);
        eventWriter.add(eElement);
        eventWriter.add(end);
    }
}

5.2. Test the code

The following uses a main method to test.

Run the program to write the articles.rss file. It uses the java.time API to create the publication date in the RFC 1123 format required by the RSS specification.

package de.vogella.rss.tests;

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;

import de.vogella.rss.model.Feed;
import de.vogella.rss.model.FeedMessage;
import de.vogella.rss.write.RSSFeedWriter;

public class WriteTest {

    public static void main(String[] args) {
        // create the rss feed
        String copyright = "Copyright held by Lars Vogel";
        String title = "Eclipse and Java Information";
        String description = "Eclipse and Java Information";
        String language = "en";
        String link = "https://www.vogella.com/";
        String pubdate = DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now());
        Feed rssFeed = new Feed(title, link, description, language, copyright, pubdate, new ArrayList<>());

        // now add one example entry
        FeedMessage message = new FeedMessage("RSSFeed", "This is a description",
                "https://www.vogella.com/tutorials/RSSFeed/article.html", "nonsense@somewhere.de (Lars Vogel)",
                "https://www.vogella.com/tutorials/RSSFeed/article.html");
        rssFeed.messages().add(message);

        // now write the file
        RSSFeedWriter writer = new RSSFeedWriter(rssFeed, "articles.rss");
        try {
            writer.write();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

6. Links and literature

Home Tutorials Training Consulting Books Company Contact us


Get more...