Android – XML Parser

Serviciu Web

Un serviciu web este o modalitate standardizată de a pune la dispoziție utilizatorilor o aplicație web, pe Internet. Multitudinea de protocoale și standarde disponibile au dat posibilitatea comunicării între aplicații pe sisteme aflate la distanțe mari. Astfel, există sisteme ce oferă servicii de informare și procesare a informațiilor care în general sunt independente de platforma hardware; accesul la acestea se face prin servicii web.

android_xml_100

Exemple clasice de servicii web de informare sunt obţinerea de informaţii referitoare la schimbul valutar sau condițiilor climatice intr-un anumit punct de pe glob.

WSDL

O componentă importantă în cadrul unui serviciu web este WSDL. WSDL (engleză Web Services Description Language) sau Limbajul de Descriere a Serviciilor Web este un limbaj bazat pe XML ce oferă un model de descriere a serviciilor web.

WSDL este adesea utilizat în combinație cu SOAP și XML Schema pentru a oferi servicii Web. Un program client conectându-se la un serviciu web poate citi WSDL pentru a determina ce funcții sunt permise de acest server. Orice tip de date special, folosit și implementat în fișierul WSDL apare sub formă de XML Schema. De asemenea clientul poate utiliza SOAP pentru ca eventual să apeleze una dintre funcțiile conținute de WSDL.

Servicii REST

Representational State Transfer (REST) este un stil arhitectural software pentru sisteme hipermedia distribuite, cum ar fi world wide web. În momentul de faţă se evidenţiază trei tipuri de arhitecturi pentru serviciile web: arhitectura REST, arhitectura RPC şi un hibrid între REST şi RPC(Remote Procedure Call).

Arhitectura REST este alcătuită din clienţi și servere. Clienții inițiază o cerere către server, iar serverul construiește un răspuns pe baza cererii, răspuns care este apoi transmis clientului. Cererea și răspunsul sunt construite ca fiind reprezentări ale unei resurse. O resursă poate fi orice concept care poate fi definit într-un mod specific într-un document. O reprezentare a unei resurse este, de obicei, un document care descrie starea actuală a resursei (la răspuns) sau o stare dorită (la cerere).

„ În HTTP, metodele cela mai comune sunt PUT, GET, POST şi DELETE, care corespund operațiilor Create, Retrieve, Update și Delete (CRUD) pe baze de date. În practică, majoritatea aplicațiilor Web utilizează doar GET si POST.

Triunghiul REST

rest-triangle

Interfața = verb; Tipurile de conținut; Identificator de resurse = substantiv (noun). => REST definește substantive neconstrânse a.î. clienții nu trebuie să cunoască întreaga resursă.

Integrarea unui serviciu web se poate realiza prin XML sau JSON.

XML

XML (eXtensible Markup Language) este un limbaj de marcare (markup) care definește o serie de  reguli pentru reprezentarea documentelor într-un format care poate fi citit foarte ușor și de om, dar și de calculator. XML-ul a fost creat de la bun început ca un standard de interschimbare a datelor, scopul proiectării lui fiind de a accentua simplitatea, generalitatea și utilizabilitatea pe Internet.

Parsare XML

Document Object Model, DOM – documentul XML este integral încărcat în memorie sub forma unui arbore ce poate fi parcurs şi examinat de către aplicaţie;

Simple API for XML, SAX – este un model bazat pe evenimente (cum ar fi începutul unui element sau atribut) ce sunt urmărite pe măsură ce documentul este parcurs. Nu necesită încărcarea întregului document în memorie, iar datele sunt livrate pe măsură ce se înaintează în cadrul structurii XML.

XML Pull Parser –  este un model bazat pe XMLPULL V1 API .  Android propune spre utilizare în a parsa  XML clasa  XmlPullParser class.  Acest parser nu este valabil în versiunea standard de Java, dar este similar cu Stax.

În Android  este recomandată utilizarea lui  XmlPullParser. Dispune de un API relativ simplu comparativ cu SAX și DOM, este rapid și necesită mai puțină memorie decât DOM API.

chart

Exemplu implementare

Pentru a exemplifica modalitatea de utilizare a celor trei parsere vom utiliza un RSS feed, mai precis pe cel al blogului:  https://magdabadita.wordpress.com/feed/

DOM

BaseFeedParser.java


public abstract class BaseFeedParser implements FeedParser {

// names of the XML tags

protected static final String PUB_DATE = "pubDate";

protected static final String DESCRIPTION = "description";

protected static final String LINK = "link";

protected static final String TITLE = "title";

protected static final String ITEM = "item";

final URL feedUrl;

protected BaseFeedParser(String feedUrl)

{

try

{

this.feedUrl = new URL(feedUrl);

}

catch (MalformedURLException e)

{

throw new RuntimeException(e);

}

}

protected InputStream getInputStream()

{

try

{

return feedUrl.openConnection().getInputStream();

}

catch (IOException e)

{

throw new RuntimeException(e);

}

}

}

DomFeedParser.java


public class DomFeedParser extends BaseFeedParser

{

protected DomFeedParser(String feedUrl)

{

super(feedUrl);

}

public List<RSSFeed> parse()

{

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

List<RSSFeed> messages = new ArrayList<RSSFeed>();

try

{

DocumentBuilder builder = factory.newDocumentBuilder();

Document dom = builder.parse(this.getInputStream());

Element root = dom.getDocumentElement();

NodeList items = root.getElementsByTagName(BaseFeedParser.ITEM);

for (int i=0;i<items.getLength();i++)

{

RSSFeed message = new RSSFeed();

Node item = items.item(i);

NodeList properties = item.getChildNodes();

for (int j=0; j<properties.getLength(); j++)

{

Node property = properties.item(j);

String name = property.getNodeName();

if (name.equalsIgnoreCase(TITLE))

{

message.setTitle(property.getFirstChild().getNodeValue());

}

else

if (name.equalsIgnoreCase(LINK))

{

message.setLink(property.getFirstChild().getNodeValue());

}

else

if (name.equalsIgnoreCase(DESCRIPTION))

{

StringBuilder text = new StringBuilder();

NodeList chars = property.getChildNodes();

for (int k=0;k<chars.getLength();k++)

{

text.append(chars.item(k).getNodeValue());

}

message.setDescription(text.toString());

}

else

if (name.equalsIgnoreCase(PUB_DATE))

{

message.setPubDate(property.getFirstChild().getNodeValue());

}

}

messages.add(message);

}

}

catch (Exception e)

{

throw new RuntimeException(e);

}

return messages;

}

}

SAX

RssHandler.java


public class RssHandler extends DefaultHandler

{

private List<RSSFeed> messages;

private RSSFeed currentMessage;

private StringBuilder builder;

public List<RSSFeed> getMessages()

{

return this.messages;

}

@Override

public void characters(char[] ch, int start, int length) throws SAXException

{

super.characters(ch, start, length);

builder.append(ch, start, length);

}

@Override

public void endElement(String uri, String localName, String name) throws SAXException

{

super.endElement(uri, localName, name);

if (this.currentMessage != null){

if (localName.equalsIgnoreCase(BaseFeedParser.TITLE))

{

currentMessage.setTitle(builder.toString());

}

else

if (localName.equalsIgnoreCase(BaseFeedParser.LINK))

{

currentMessage.setLink(builder.toString());

}

else

if (localName.equalsIgnoreCase(BaseFeedParser.DESCRIPTION))

{

currentMessage.setDescription(builder.toString());

}

else

if (localName.equalsIgnoreCase(BaseFeedParser.PUB_DATE))

{

currentMessage.setPubDate(builder.toString());

}

else

if (localName.equalsIgnoreCase(BaseFeedParser.ITEM))

{

messages.add(currentMessage);

}

builder.setLength(0);

}

}

@Override

public void startDocument() throws SAXException

{

super.startDocument();

messages = new ArrayList<RSSFeed>();

builder = new StringBuilder();

}

@Override

public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException

{

super.startElement(uri, localName, name, attributes);

if (localName.equalsIgnoreCase(BaseFeedParser.ITEM))

{

this.currentMessage = new RSSFeed();

}

}

}

SaxFeedParser.java


public class SaxFeedParser extends BaseFeedParser

{

protected SaxFeedParser(String feedUrl)

{

super(feedUrl);

}

public List<RSSFeed> parse()

{

List<RSSFeed> list = new ArrayList<RSSFeed>();

SAXParserFactory factory = SAXParserFactory.newInstance();

try

{

SAXParser parser = factory.newSAXParser();

RssHandler handler = new RssHandler();

parser.parse(this.getInputStream(), handler);

list = handler.getMessages();

Log.e("list sax", list.toString());

}

catch (Exception e)

{

throw new RuntimeException(e);

}

return list;

}

}

XML Pull Parser

NewsFeedParser.java

</pre>
public class NewsFeedParser

{

private InputStream urlStream;

private XmlPullParserFactory factory;

private XmlPullParser parser;

private List<RSSFeed> rssFeedList;

private RSSFeed rssFeed;

private String urlString;

private String tagName;

private String title;

private String link;

private String description;

private String category;

private String pubDate;

private String guid;

private String feedburner;

public static final String ITEM = "item";

public static final String CHANNEL = "channel";

public static final String TITLE = "title";

public static final String LINK = "link";

public static final String DESCRIPTION = "description";

public static final String CATEGORY = "category";

public static final String PUBLISHEDDATE = "pubDate";

public static final String GUID = "guid";

public static final String FEEDBURNERORIGLINK = "feedburner:origLink";

public NewsFeedParser(String urlString)

{

this.urlString = urlString;

}

public static InputStream downloadUrl(String urlString) throws IOException

{

URL url = new URL(urlString);

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setRequestMethod("GET");

conn.setDoInput(true);

conn.connect();

InputStream stream = conn.getInputStream();

return stream;

}

public List<RSSFeed> parse()

{

try

{

int count = 0;

factory = XmlPullParserFactory.newInstance();

parser = factory.newPullParser();

urlStream = downloadUrl(urlString);

parser.setInput(urlStream, null);

int eventType = parser.getEventType();

boolean done = false;

rssFeed = new RSSFeed();

rssFeedList = new ArrayList<RSSFeed>();

while (eventType != XmlPullParser.END_DOCUMENT && !done)

{

tagName = parser.getName();

switch (eventType)

{

case XmlPullParser.START_DOCUMENT:

break;

case XmlPullParser.START_TAG:

if (tagName.equals(ITEM))

{

rssFeed = new RSSFeed();

}

if (tagName.equals(TITLE))

{

title = parser.nextText().toString();

}

if (tagName.equals(LINK))

{

link = parser.nextText().toString();

}

if (tagName.equals(DESCRIPTION))

{

description = parser.nextText().toString();

}

if (tagName.equals(CATEGORY))

{

category = parser.nextText().toString();

}

if (tagName.equals(PUBLISHEDDATE))

{

pubDate = parser.nextText().toString();

}

if (tagName.equals(GUID))

{

guid = parser.nextText().toString();

}

if (tagName.equals(FEEDBURNERORIGLINK))

{

feedburner = parser.nextText().toString();

}

break;

case XmlPullParser.END_TAG:

if (tagName.equals(CHANNEL))

{

done = true;

} else

if (tagName.equals(ITEM))

{

rssFeed = new RSSFeed(title, link, description, category, pubDate,

guid,

feedburner);

rssFeedList.add(rssFeed);

}

break;

}

eventType = parser.next();

}

}

catch (Exception e)

{

e.printStackTrace();

}

Log.e("list xml pull", rssFeedList.toString());

return rssFeedList;

}

}

Resurse

– cod sursa: https://docs.google.com/file/d/0B-QojgLEXJyhLUxaR1ZWN0lSNUE/edit?usp=sharing

– XML Pull Parser : http://developer.android.com/reference/org/xmlpull/v1/XmlPullParser.html

– DOM: http://www.w3schools.com/dom/

– SAX: http://www.saxproject.org/

– acest tutorial a fost publicat și pe site-ul Comunității de Android România 

Advertisements
Android – XML Parser

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s