PlanetXML

RSS Parser in Java

Ein kleiner RSS-Parser inklusive Grafischer Oberfläche. Die Einträge werden mit einem Swing TableModel dargestellt.

Screenshot

Screenshot

Klasse RSSItem

/**
 * Enthält die Informationen zu einem Item innerhalb einer RSS-Datei. 
 */
class RSSItem
{
    private String title       = null;
    private String url         = null;
    private String description = null;

    public RSSItem() {}

    public RSSItem(String title,String url,String description)
    {
        this.title       = title;
        this.url         = url;
        this.description = description;
    }

    public void setTitle(String title)
    {
        this.title = title;
    }

    public String getTitle()
    {
        return title;
    }

    public void setURL(String url)
    {
        this.url = url;
    }

    public String getURL()
    {
        return url;
    }

    public void setDescription(String description)
    {
        this.description = description;
    }

    public String getDescription()
    {
        return description;
    }
}

Klasse RSSParser

import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import javax.xml.parsers.*;
import java.util.ArrayList;

/**
 * Parst eine RSS-Datei im RSS 0.9 oder 0.91 Format (ohne Verwendung von
 * Namespaces).
 */
class RSSParser extends DefaultHandler
{
    private ArrayList    items        = null;
    private RSSItem      currentItem  = null;
    private RSSItem      channel      = null;

    /** Character Data innerhalb des aktuellen Tags. */
    private StringBuffer stringBuffer = null;

    private boolean      inItem       = false;
    private boolean      inChannel    = false;

    public RSSParser(String path)
    {
        // currentItem wird in startElement initialisiert
        items        = new ArrayList();
        stringBuffer = new StringBuffer();

        try {
            // Neuen SAX-Parser erzeugen
            SAXParserFactory factory   = SAXParserFactory.newInstance();
            SAXParser        saxParser = factory.newSAXParser();

            // XML Datei parsen, die entsprechenden Methoden des DefaultHandler
            // werden als Callback aufgerufen.
            // TODO: Validierung deaktivieren, da sonst versucht wird eine DTD
            //       aus dem Internet zu laden.
            System.out.println("Parsing " + path);
            saxParser.parse(path,this);
        }
        catch (Exception e) {
            //System.out.println(e);
            e.printStackTrace();
        }
    }

    public void startElement(String namespaceURI, String localName, String
                             qName, Attributes atts) throws SAXException
    {
        // "...".equals() vermeidet die Auslösung von NullPointerException beim Vergleich.
        if ("channel".equals(qName)) {
            channel   = new RSSItem();
            inChannel = true;
        }
        else if ("item".equals(qName)) {
            currentItem = new RSSItem();
            inItem      = true;
        }
        stringBuffer.setLength(0);
        // System.out.println("startElement : " + qName);
    }

    public void endElement(String namespaceURI, String localName, String qName)
    {
        if ("channel".equals(qName)) {
            inChannel = false;
        }
        else if ("item".equals(qName)) {
            items.add(currentItem);
            inItem = false;
        }
        else if (inItem) {
            String str = stringBuffer.toString().trim();
            if ("title".equals(qName)) {
                currentItem.setTitle(str);
            }
            else if ("link".equals(qName)) {
                currentItem.setURL(str);
            }
            else if ("description".equals(qName)) {
                currentItem.setDescription(str);
            }
        }
        else if (inChannel) {
            String str = stringBuffer.toString().trim();
            if ("title".equals(qName)) {
                channel.setTitle(str);
            }
            else if ("link".equals(qName)) {
                channel.setURL(str);
            }
            else if ("description".equals(qName)) {
                channel.setDescription(str);
            }
        }
        // System.out.println("endElement : " + qName);
    }

    public void characters(char ch[], int start, int length)
    {
        if (inItem || inChannel) {
            stringBuffer.append(ch,start,length);
        }
    }

    /** Gibt Informationen über diesen Channel als <code>RSSItem</code> zurück. */
    public RSSItem getChannel()
    {
        return channel;
    }

    /** Gibt das Item mit dem Index <code>i</code> zurück. */
    public RSSItem getItem(int i)
    {
        return (RSSItem)items.get(i);
    }

    /** Gibt die Anzahl Items zurück. */
    public int itemCount()
    {
        return items.size();
    }
}

Klasse RSSTableModel

/**
 * TableModel für Daten im RSS-Format. Die Tabelle hat drei Spalten für Titel, URL und Beschreibung.
 */
public class RSSTableModel extends javax.swing.table.AbstractTableModel
{
    private static final int      COLUMNCOUNT = 3;
    private static final String[] COLUMNNAMES = new String[]{"Title","URL","Description"};

    private RSSParser parser = null;

    /** Lädt die angegebene Datei mit dem <code>RSSParser</code>. */
    public RSSTableModel(String path)
    {
        parser = new RSSParser(path);
    }

    /**
     * Gibt die Beschreibung dieses Channels als <code>RSSItem</code> zurück.
     * Der Channel enthält genau wie die einzelnen Items die Felder Titel, URL
     * und Beschreibung.
     */
    public RSSItem getChannel()
    {
        return parser.getChannel();
    }

    public int getColumnCount()
    {
        return COLUMNCOUNT;
    }

    public int getRowCount()
    {
        return parser.itemCount();
    }

    public String getColumnName(int col) {
        return COLUMNNAMES[col];
    }

    /**
     * Gibt immer <code>false</code> zurück.
     */
    public boolean isCellEditable(int row, int col)
    {
        return false;
    }

    public void setValueAt(Object aValue, int row, int col)
    {
    }

    public Object getValueAt(int row, int col)
    {
        RSSItem item = parser.getItem(row);
        switch (col) {
            case 0:
                return item.getTitle();
            case 1:
                return item.getURL();
            case 2:
                return item.getDescription();
        }
        return "";
    }

    /**
     * Gibt immer die String-Klasse zurück.
     */
    public Class getColumnClass(int c)
    {
        return "".getClass();
    }
}

Klasse Main

/**
 * GUI für das <code>RSSTableModel</code>.
 */
public class Main extends javax.swing.JFrame
{
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable      jTable1;
    private RSSTableModel           model;

    /**
     * Erzeugt einen <code>JFrame</code> der eine scrollbare <code>JTable</code> enthält.
     */
    public Main(String path) {
        jScrollPane1 = new javax.swing.JScrollPane();
        jTable1      = new javax.swing.JTable();

        model        = new RSSTableModel(path);

        jTable1.getTableHeader().setReorderingAllowed(false);

        getContentPane().setLayout(new java.awt.GridLayout(1, 0));

        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent e) {
                System.exit(0);
            }
        });

        jScrollPane1.setMinimumSize(new java.awt.Dimension(200, 100));
        jScrollPane1.setPreferredSize(new java.awt.Dimension(200, 100));

        jTable1.setModel(model);

        jTable1.setMinimumSize(new java.awt.Dimension(150, 100));
        jTable1.setPreferredScrollableViewportSize(new java.awt.Dimension(0, 0));
        jScrollPane1.setViewportView(jTable1);

        getContentPane().add(jScrollPane1);

        setTitle("RSS-Parser - " + model.getChannel().getTitle());

        pack();
    }

    public static void main(String args[])
    {
        if (args.length != 1) {
            System.out.println("Aufruf mit RSS-Datei als Parameter");
            System.exit(1);
        }
        new Main(args[0]).show();
    }
}