Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> RSS клиент 
V
    Опции темы
Shklyar
Дата 22.8.2008, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 211
Регистрация: 28.11.2007
Где: Kyiv

Репутация: 2
Всего: 3



Добрый день.
Вот решил делать RSS клиент как свою первую программу на Java.
Подскажите:
1. Что обязательно к прочтению?
2. Какие необходимы классы? Мысли такие: непосредственно RSSReader, он будет создавать Article-ы и где-то должен присутствовать SubscriptionToFeeds. А где использовать интерфейсы? Может где-то паттерн? Какой? И что из API мне нужно? Спрашиваю т.к. опыта нет..
Спасибо.
--------------------
https://www.youtube.com/watch?v=JZN8Xaebs_U
PM WWW   Вверх
LSD
Дата 22.8.2008, 15:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Ну для начала почитай описание формата RSS и про сам XML. Потом парсинг XML в Java (есть пара статей в FAQ).


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Shklyar
Дата 25.8.2008, 12:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 211
Регистрация: 28.11.2007
Где: Kyiv

Репутация: 2
Всего: 3



Почитал, научился парсить XML (по примеру из FAQ, более детально буду разбираться непосредственно при решении своей задачи). Подскажите, что такое RSS парсер.

2. Помогите представить общую картину желаемого приложения (все-же хочу начать с uml диаграммы классов).
--------------------
https://www.youtube.com/watch?v=JZN8Xaebs_U
PM WWW   Вверх
Shklyar
Дата 27.8.2008, 19:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 211
Регистрация: 28.11.2007
Где: Kyiv

Репутация: 2
Всего: 3



Несмотря на то, что какого-то представления о том, как будет выглядеть программа целиком у меня нет, я решил попробовать написать ту часть, где происходит парсинг XML или RSS? Собственно вот код. Покричите, подскажите как правильно писать.
Код
package rssclient;

/**
 *
 * @author Oleg
 */
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        try {
            for (Article article : SAXHandler.parse("rss.xml"))
                System.out.println("Title: " + article.getTitle() + "\n" +
                "Date: " + article.getDate() + "\n" +
                "Link: " + article.getLink() + "\n" +
                "Description: " + article.getSummary() + "\n");
        } catch(Exception e) {
            System.out.println(e);
        }
    }

}


Код
package rssclient;

/**
 *
 * @author Oleg
 */
public class Article {
    private String title;
    private String date;
    private String link;
    private String summary;
    
    public Article() {
    }
    
    /**
     * 
     * @param title
     * @param link
     * @param summary
     */
    public Article(String title, String date, String link, String summary) {
        setTitle(title);
        setDate(date);
        setLink(link);
        setSummary(summary);
    }
    
    public void setTitle(String t) {
        title = t;
    }
    public String getTitle() {
        return title;
    }
    
    public void setDate(String d) {
        date = d;
    }
    public String getDate() {
        return date;
    }
    
    public void setLink(String l) {
        link = l;
    }
    public String getLink() {
        return link;
    }
    
    public void setSummary(String s) {
        summary = s;
    }
    public String getSummary() {
        return summary;
    }
}


Код
package rssclient;

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

/**
 *
 * @author Oleg
 */
public class SAXHandler extends DefaultHandler {
    private ArrayList<Article> articles;
    private boolean isItemTag = false;
    private boolean isDateTag = false;
    private boolean isTitleTag = false;
    private boolean isLinkTag = false;
    private boolean isSummaryTag = false;
    
    private String title;
    private String date;
    private String link;
    private String summary;
    
    private Article[] getArticles() {
        return articles.toArray(new Article[articles.size()]);
    }
    
    @Override
    public void startDocument() throws SAXException {
        articles = new ArrayList<Article>();
    }
    
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        if (isItemTag) {
            isTitleTag = "title".equals(qName);
            isDateTag = "date".equals(qName);
            isLinkTag = "link".equals(qName);
            isSummaryTag = "summary".equals(qName);
        } else isItemTag = "item".equals(qName);
    }
    
    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        if (isTitleTag) title = new String(ch, start, length);
        else if (isDateTag) date = new String(ch, start, length);
        else if (isLinkTag) link = new String(ch, start, length);
        else if (isSummaryTag) summary = new String(ch, start, length);
    }
    
    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        if ("item".equals(qName)) {
            articles.add(new Article(title, date, link, summary));
            isItemTag = false;
            isTitleTag = false;
            isLinkTag = false;
            isSummaryTag = false;
            title = null;
            date = null;
            link = null;
            summary = null;
        } else if ("title".equals(qName)) isTitleTag = false;
        else if ("date".equals(qName)) isDateTag = false;
        else if ("link".equals(qName)) isLinkTag = false;
        else if ("summary".equals(qName)) isSummaryTag = false;
    }
    
    @Override
    public void endDocument() throws SAXException {
    }
    
    /**
     * 
     * @param xml the path to *.xml file
     * @return array of Articles
     * @throws java.lang.Exception
     */
    public static Article[] parse(String xml) throws Exception {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parser = factory.newSAXParser();
        
        SAXHandler handler = new SAXHandler();
        parser.parse(new File(xml), handler);
        
        return handler.getArticles();
    }
}


Код
import org.junit.*;
import static org.junit.Assert.*;
import java.util.*;
import rssclient.*;

/**
 *
 * @author Oleg
 */
public class TestArticle {
    @Test
    public void testArticleSetGetTitle() {
        Article article = new Article();
        article.setTitle("Title1");
        assertEquals("Title1", article.getTitle());
    }
    
    @Test
    public void testSecondConstructor() {
        Article article = new Article("T", "D", "L", "S");
        assertEquals(true, article.getTitle()=="T" && article.getDate()=="D" &&
                article.getLink() == "L" && article.getSummary()=="S");
    }
    
    public static junit.framework.Test suite() {
        return new junit.framework.JUnit4TestAdapter(TestArticle.class);
    }
    
    public static void main(String[] args) {
        org.junit.runner.JUnitCore.main("TestArticle");
    }
}


Код
<?xml version="1.0" encoding="UTF-8"?>
<channel>
        <title>chanelTitle</title>
        <date>Tue, 26 Aug 2008 11:12:27 +0000</date>
        <link>chanelLink</link>
        <summary>chanelSummary</summary>
    <item>
        <title>Title 1</title>
        <date>Tue, 26 Aug 2008 11:24:48 +0000</date>
        <link>Link 1</link>
        <summary>Summary 1</summary>
    </item>
    <item>
        <title>Title 2</title>
        <link>Link 2</link>
        <summary>Summary 2</summary>
    </item>
    <item>
        <title>Title 3</title>
        <link>Link 3</link>
        <summary>Summary 3</summary>
    </item>
    <item>
        <title>Title 4</title>
        <link>Link 4</link>
        <summary>Summary 4</summary>
    </item>
</channel>


И появился ряд маленьких вопросов:
1. Тут, как и в примере из FAQ, с которого я это делал, xml читаем из файла. А как в реальном клиенте? Т.е. как изменится строчка
Код
parser.parse(new File(xml), handler);
?
2. JavaDoc. Что нужно комментировать, а что нет?
3. RSS. Если посмотрите мой пример xml-я - увидите, что сперва идет <channel> со своим описанием, потом - <item>-ы. Как и зачем использовать описания <channel> (интересует логика, как прочитать как-бы понятно)?
4. Есть разные форматы RSS, значит мне надо наследовать мой SAXHandler и реализовать наследников для разных форматов? ЗЫ: тут можно использовать паттерн абстрактная фабрика (как-то просматривал статьи про паттерны, могу все путать)?
5. Планирую сделать "caching of articles", ну т.е. писать все в БД. Подскажите, как различать новые итемы от существующих (наверное сравнивать какие-то поля. какие поля? есть какое-то общепринятое решение)?
6. По тестам. Что необходимо тестить в приведенном коде?
7. Последнее. Класс Article. Полей в нем достаточно?
--------------------
https://www.youtube.com/watch?v=JZN8Xaebs_U
PM WWW   Вверх
ivg
Дата 28.8.2008, 01:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Autonomous R&D
**


Профиль
Группа: Участник
Сообщений: 686
Регистрация: 8.2.2006
Где: Екатеринбург

Репутация: 33
Всего: 81



Для полноты картины: wiki: RSS (внизу есть ссылки на спецификации), Open Source RSS & RDF Tools in Java(На случай если вдруг вы захотите использовать готовые решения, а не изобретать своё);
1. В реальном клиенте, а точнее в классе/интерфейсе, предназначенном непосредственно для использования в клиентском коде, будет куча одноимённых методов, различающихся типом входных параметров. Например содержимое входного xml может быть предано как String, File, InputStream и т.д. Естественно никакого handler'а в параметрах не будет - это наше дело, каким способом мы парсим xml.
2. Комментировать лучше всё, а вот JavaDoc формировать по классам/пакетам, которые могут быть использованы клиентом, исключив private поля/методы/внутренние классы;
3. См. первую ссылку.
4.
Цитата(Shklyar @  27.8.2008,  22:04 Найти цитируемый пост)
Есть разные форматы RSS, значит мне надо наследовать мой SAXHandler и реализовать наследников для разных форматов?

Не факт. Как вы будете определять объект какого класса инстанциировать? Заставлять клиента определять? - Нехорошо. На основе содержимого xml - для этого нужно его распарсить. Может лучшим решением будет распарсить в каком то общем виде, определить формат, а потом уже сформировать ответ для клиента.
5. См. первую ссылку.
6. Ну классы модели, представляющие из себя POJO классы, по моему, тестировать ни к чему. Тестировать надо функционал, логику работы самого парсера. На вход даёте, заранее определённый xml, получаете результат и проверяете его.
7. См. первую ссылку. Кстати, по моему, результат работы парсера, лучше выдавать как объект одного класса, например RSSChannel или типа того.
В качестве резюме, попробую всё таки посоветовать использовать готовое решение, а не "изобретать велосипед". smile
PM MAIL   Вверх
Nudnik
Дата 28.8.2008, 08:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 33
Регистрация: 15.9.2007

Репутация: нет
Всего: нет



а не красивее ли будет попробовать с помощью JAXB?
PM MAIL   Вверх
Shklyar
Дата 28.8.2008, 12:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 211
Регистрация: 28.11.2007
Где: Kyiv

Репутация: 2
Всего: 3



Цель этой программы - получить опыт, маленький. Вот и приглянулась мне идея RSSClient-а, так программа будет включать работу с xml, с БД, чем-то еще. По этому, как для обучения, наверное, лучше "изобретать велосипед".
Подскажите что счас (маленькое) сделать?
Сенкс.
--------------------
https://www.youtube.com/watch?v=JZN8Xaebs_U
PM WWW   Вверх
LSD
Дата 28.8.2008, 14:29 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Продолжай делать свой RSS клиент. Раз с  парсингом XML разобрался, делай получение RSS из интернета (поищи по форуму: URL openConnection) . Потом попробуй совместить код парсинга и чтения из интернета.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Shklyar
Дата 28.8.2008, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 211
Регистрация: 28.11.2007
Где: Kyiv

Репутация: 2
Всего: 3



Дык а это не HTTPClient (такое когда-то делал)?
--------------------
https://www.youtube.com/watch?v=JZN8Xaebs_U
PM WWW   Вверх
LSD
Дата 28.8.2008, 16:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Можно и HTTPClient использовать, раз ты с ним знаком.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Shklyar
Дата 28.8.2008, 16:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 211
Регистрация: 28.11.2007
Где: Kyiv

Репутация: 2
Всего: 3



Код
package rssclient;

import java.net.*;
import java.io.*;

/**
 *
 * @author Oleg
 */
public class HTTPClient {
    private String answer = "";
    
    public HTTPClient(String url) {
        try {
            URL s = new URL(url);
            URLConnection sc = s.openConnection();
            
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(sc.getInputStream()));
            String inputLine;
            while ((inputLine = in.readLine()) != null)
                answer += inputLine + "\n";
            in.close();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public String getAnswer() {
        return answer;
    }
}


И вызываю его:
Код
        HTTPClient httpClient = new HTTPClient("http://rss.net/rss.xml");
        System.out.println(httpClient.getAnswer());


А как модифицировать
Код
parser.parse(new File(xml), handler);
?
--------------------
https://www.youtube.com/watch?v=JZN8Xaebs_U
PM WWW   Вверх
Shklyar
Дата 28.8.2008, 16:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 211
Регистрация: 28.11.2007
Где: Kyiv

Репутация: 2
Всего: 3



Переделал, чуток HTTPClient:
Код
package rssclient;

import java.net.*;
import java.io.*;

/**
 *
 * @author Oleg
 */
public class HTTPClient {
    private String answer = "";
    private InputStream isAnswer;
    
    public HTTPClient(String url) {
        try {
            URL s = new URL(url);
            URLConnection sc = s.openConnection();
            
            isAnswer = sc.getInputStream();
            
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(isAnswer));
            String inputLine;
            while ((inputLine = in.readLine()) != null)
                answer += inputLine + "\n";
            in.close();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public String getAnswer() {
        return answer;
    }
    
    public InputStream getISAnswer() {
        return isAnswer;
    }
}
, добавил, в SAXHandler метод:
Код
    public static Article[] parse(InputStream httpAnswer) throws Exception {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parser = factory.newSAXParser();
        
        SAXHandler handler = new SAXHandler();
        parser.parse(httpAnswer, handler);
        
        return handler.getArticles();
    }

И вызываю все так:
Код
        try {
            HTTPClient httpClient = new HTTPClient("http://rss.net/rss.xml");
            for (Article article : SAXHandler.parse(httpClient.getISAnswer()))
                System.out.println("Title: " + article.getTitle() + "\n" +
                "Date: " + article.getDate() + "\n" +
                "Link: " + article.getLink() + "\n" +
                "Description: " + article.getSummary() + "\n");
        } catch(Exception e) {
            System.out.println(e);
        }

И получаю org.xml.sax.SAXParseException: Premature end of file.
Почему?
--------------------
https://www.youtube.com/watch?v=JZN8Xaebs_U
PM WWW   Вверх
Shklyar
Дата 28.8.2008, 22:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 211
Регистрация: 28.11.2007
Где: Kyiv

Репутация: 2
Всего: 3



К предыдущему посту:
Что происходит - понятно (функция httpClient.getISAnswer() возвращает некую пустоту), но почему?
ЗЫ: плохое имя придумал для переменной "isAnswer", как answer типа InputStream, очень смахивает на boolean "это answer?". Посоветуйте лучшее имя.

Добавлено через 2 минуты и 49 секунд
Классссс
--------------------
https://www.youtube.com/watch?v=JZN8Xaebs_U
PM WWW   Вверх
Shklyar
Дата 28.8.2008, 22:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 211
Регистрация: 28.11.2007
Где: Kyiv

Репутация: 2
Всего: 3



К предыдущему посту:
Что происходит - понятно (функция httpClient.getISAnswer() возвращает некую пустоту), но почему?
ЗЫ: плохое имя придумал для переменной "isAnswer", как answer типа InputStream, очень смахивает на boolean "это answer?". Посоветуйте лучшее имя.
--------------------
https://www.youtube.com/watch?v=JZN8Xaebs_U
PM WWW   Вверх
LSD
Дата 30.8.2008, 12:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Не надо никакого BufferedReader и чтения в промежуточный буфер. Скармливай парсеру просто InputStream, тот сам с кодировкой разберется.

Просто добавь в твой SAXHandler метод парсинга. Передаеш туда URL, он открывает URLConnection и сразу же парсит полученный результат. После чего закрывает соединение.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0607 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.