Java-Android. Проблема парсера - PullRequest
       18

Java-Android. Проблема парсера

1 голос
/ 16 сентября 2011

Я делаю очень простое приложение для чтения RSS.Читатель работает отлично, но он только дает мне название, и я тоже хочу описание.Я очень плохо знаком с Android, и я много чего пробовал, но не могу заставить его работать.Я нашел много парсеров, но они слишком сложны для меня, поэтому я надеялся найти простое решение, так как мне нужны только заголовок и описание.Может кто-нибудь мне помочь?

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class NyhedActivity extends Activity {
    String streamTitle = "";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.nyheder);

        TextView result = (TextView)findViewById(R.id.result);

           try {
       URL rssUrl = new URL("http://tv2sport.dk/rss/*/*/*/248/*/*");
       SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();
       SAXParser mySAXParser = mySAXParserFactory.newSAXParser();
       XMLReader myXMLReader = mySAXParser.getXMLReader();
       RSSHandler myRSSHandler = new RSSHandler();
       myXMLReader.setContentHandler(myRSSHandler);
       InputSource myInputSource = new InputSource(rssUrl.openStream());
       myXMLReader.parse(myInputSource);

       result.setText(streamTitle);

      } catch (MalformedURLException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
       result.setText("Cannot connect RSS!");
      } catch (ParserConfigurationException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
       result.setText("Cannot connect RSS!");
      } catch (SAXException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
       result.setText("Cannot connect RSS!");
      } catch (IOException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
       result.setText("Cannot connect RSS!");
      }


       }

       private class RSSHandler extends DefaultHandler
       {
        final int stateUnknown = 0;
        final int stateTitle = 1;
        int state = stateUnknown;

        int numberOfTitle = 0;
        String strTitle = "";
        String strElement = "";

      @Override
      public void startDocument() throws SAXException {
       // TODO Auto-generated method stub
       strTitle = "Nyheder fra ";
      }

      @Override
      public void endDocument() throws SAXException {
       // TODO Auto-generated method stub
       strTitle += "";
       streamTitle = "" + strTitle;
      }

      @Override
      public void startElement(String uri, String localName, String qName,
        Attributes attributes) throws SAXException {
       // TODO Auto-generated method stub
       if (localName.equalsIgnoreCase("title"))
       {
        state = stateTitle;
        strElement = "";
        numberOfTitle++;
       }
       else
       {
        state = stateUnknown;
       }
      }

      @Override
      public void endElement(String uri, String localName, String qName)
        throws SAXException {
       // TODO Auto-generated method stub
       if (localName.equalsIgnoreCase("title"))
       {
        strTitle += strElement + "\n"+"\n";
       }
       state = stateUnknown;
      }

      @Override
      public void characters(char[] ch, int start, int length)
        throws SAXException {
       // TODO Auto-generated method stub
       String strCharacters = new String(ch, start, length);
       if (state == stateTitle)
       {
        strElement += strCharacters;
       }
      }
    }

}

Ответы [ 3 ]

1 голос
/ 17 сентября 2011

Kano,

Вы можете упростить свою жизнь и получить первоклассную производительность , используя SJXP для написания этого анализатора RSS-каналов с (отказ от ответственности: я являюсьавтор).

SJXP - это очень-очень тонкий слой абстракции , который расположен поверх API XML Pull Parsing (Android предоставляет свой собственный, поэтому у вас есть только зависимость sjxp.JAR, XPP3для любой другой платформы) и позволяет использовать XPath-подобные правила синтаксического анализа для сопоставления простых правил с определенными местами документа, а затем сообщать при разборе, какую информацию вы хотите получить из этих мест.

Я написал пример проекта Eclipseдля вас, который анализирует этот канал TV2 Sports для вас за 6 минут (я свяжу его внизу).

Основной метод выглядит следующим образом, поэтому вы получите представление о потоке:

public static void main(String[] args) throws IllegalArgumentException,
    XMLParserException, IOException {
// Location we want to parse.
URL feedURL = new URL("http://tv2sport.dk/rss/*/*/*/248/*/*");

// List we will hold all parsed stories in.
List<Item> itemList = new ArrayList<Item>();

// Get all the rules we will use to parse this file
IRule[] rules = createRules();

// Create the parser and populate it with the rules.
XMLParser<List<Item>> parser = new XMLParser<List<Item>>(rules);

// Parse the RSS feed.
parser.parse(feedURL.openStream(), itemList);

// Print the results.
System.out.println("Parsed " + itemList.size() + " RSS items.");

for (Item i : itemList)
    System.out.println("\t" + i);
}

Вы видите, что процесс начинается с создания нашего Списка для хранения наших Предметов, когда мы анализируем их из документа.Затем мы получаем набор IRule экземпляров для парсера, затем создаем парсер и даем ему правила для использования во время работы.

Затем мы вызываем метод parse для содержимогопередать и передать ему то, что называется «пользовательским объектом», точнее, просто экземпляром чего-либо, что мы хотим, чтобы оно передавало правилам при их выполнении.

В этом случае нам нужен доступв наш список, чтобы мы могли добавлять в него элементы, поэтому мы просто передаем это, и синтаксический анализатор передает его прямо в нашу IRule логику , когда она выполняется, чтобы мы могли ее использовать.

Класс Item использует простой POJO для хранения данных и делает печать приятной:

public class Item {
    public String title;
    public String description;

    @Override
    public String toString() {
        return "Item [title='" + title + "', description='" + description + "']";
    }
}

Все интересное происходит в вашей IRule, где вы определяете, на какой элемент вы нацеливаетесь (символьные данные, атрибуты).данные или просто пометить события открытия / закрытия), а затем переопределить соответствующий метод из интерфейса IRule, чтобы предоставить обработчик, который что-то делает.

Например, вот обработчик, который анализирует заголовки:

IRule<List<Item>> itemDescRule = new DefaultRule<List<Item>>(Type.CHARACTER, "/rss/channel/item/description") {
    @Override
    public void handleParsedCharacters(XMLParser<List<Item>> parser, String text, List<Item> userObject) {
        Item item = userObject.get(userObject.size() - 1);
        item.description = text;
    }
};

Вы видите, что получаете сам экземпляр экземпляра синтаксического анализатора (так что вы можете вызвать метод 'stop', если хотите досрочно прекратить анализ), вы получаететекст, который представлял собой символьные данные, и вы получаете тот «объект пользователя», который оказался нашим списком, переданным вам.

Мы берем элемент, который заполняем, из списка, даем ему описание, и этоЭто.2 строки кода.

Существует еще одна IRule, которая добавляет новый элемент в список каждый раз, когда встречается открытый тег, и это позволяет нашим последующим правилам, таким как это, просто выталкивать конечный элемент изперечислите и заполните его.

Когда вы запускаете проект, результат будет выглядеть следующим образом:

Parsed 50 RSS items.
    Item [title='Barcas bøddel beæret over Barca-føler', description='Tirsdag snød Thiago Silva Barcelona for tre point, da han headede AC Milans udligning i kassen i Champions League-kampens overtid.']
    Item [title='Guardiola: Pato hurtigere end Usain Bolt', description='FC Barcelona-træner, Josep Guardiola, er dybt imponeret af Milan-målscoreren Alexandre Patos hurtighed.']
    Item [title='Milan-profil: Vi kan nå semifinalen', description='Clarence Seedorf mener, at AC Milan kan nå semifinalerne i Champions League efter 2-2 i Barcelona.']
    <SNIP...>

Вы можете скачать весь проект Eclipse, который я создал для вас здесь .

Надеюсь, это поможет.

1 голос
/ 16 сентября 2011

Я никогда не использовал SAX, когда дело доходит до парсинга XML в Java.Я всегда использую JDOM .Он прост и действительно прост в использовании.

Чтобы прочитать XML-файл с помощью JDOM, вы создаете документ и заполняете его, используя InputStream и SAXBuilder:

SAXBuilder builder = new SAXBuilder();
Document document = builder.builder( myInputStream );

В своем опубликованномcase: myInputStream = url.openStream();

Затем вам нужно получить корень XML-документа:

Element root = document.getRootElement();

Теперь все очень просто.Поскольку я не знаю структуру XML-файла, который вы получаете, я просто предположу, что он выглядит примерно так:

<rssfeed>
  <news>
    <title> Title </title>
    <description> Description </description>
  </news>
  <news>
    <title> ... </title>
    <description> ... </description>
  </news>
  <news>
    <title> ... </title>
    <description> ... </description>
  </news>
<rssfeed>

Затем вы можете перечислить все элементы, например:

List<Element> news = root.getChildren( "news" );

Затем вы пробегаете список в цикле for-each, получая заголовок и описание (наличие класса данных для хранения этой информации поможет, например, класс News):

ArrayList<News> newsList = new ArrayList<News>();
for( Element child : news ) {
  News news = new News();
  news.setTitle( child.getChildText( "title" );
  news.setDescription( child.getChildText( "description" );
  newsList.add( news );
}

Теперь у вас есть список новостей, с которыми вы можете поиграть.

0 голосов
/ 16 сентября 2011

Надеюсь, я смогу вам помочь:

  @Override
  public void endElement(String uri, String localName, String qName)
    throws SAXException {
   // TODO Auto-generated method stub
   if (localName.equalsIgnoreCase("title"))
   {
    strTitle += strElement + "\n"+"\n";
   }
   else if (localName.equalsIgnoreCase("lead"))
   {
    lead += strElement + "\n"+"\n";
   }
  }
...