Trabalhando com XML no Android

Crie aplicativos Java para celulares

O Android é um sistema operacional e SDK moderno, de software livre, para celulares. Com ele, é possível criar poderosos aplicativos móveis. Isso fica ainda mais atraente quando seus aplicativos podem acessar serviços da Web, o que significa que você precisa falar a língua da Web: XML. Neste artigo, veremos as diferentes opções para trabalhar com XML em Android e como usá-los para criar seus próprios aplicativos em Android.

Michael Galpin, Software architect, eBay

Michael_GalpinMichael Galpin is an architect at eBay and is a frequent contributor to developerWorks. He has spoken at various technical conferences, including JavaOne, EclipseCon and AjaxWorld. To get a preview of what he is working on, follow @michaelg on Twitter.



23/Jun/2009

Introdução

Neste artigo, vamos aprender a criar aplicativos Android que funcionem em XML na Internet. Os aplicativos Android são escritos em linguagem de programação Java™, de modo que é essencial ter experiência com tecnologia Java. Para desenvolver para Android, você precisa de Android SDK. Todo o código mostrado neste artigo funciona com qualquer versão do Android SDK, mas foi usado o SDK 1.5_pre para desenvolver o código. É possível desenvolver aplicativos Android apenas com o SDK e um editor de texto, mas é muito mais fácil usar as Android Developer Tools (ADT), um plug-in do Eclipse. Para este artigo, foi usada a versão 0.9 das ADT com Eclipse 3.4.2, edição Java. Veja em Recursos links para todas essas ferramentas.


XML em Android

A plataforma Android é uma plataforma de desenvolvimento em software livre para celulares. Ele lhe dá acesso a todos os aspectos do celular em que é executado, de gráficos de baixo nível a hardware como a câmera do telefone. Com tantas possibilidades de uso do Android, talvez você se pergunte porque precisa se preocupar com XML. Não é que trabalhar com XML seja tão interessante; o interessante é trabalhar com as coisas que ele possibilita. XML é usado normalmente como formato de dados na Internet. Se quiser acessar dados na Internet, é bem possível que eles estejam em formato XML. Se você envia dados a um serviço da Web, talvez você também precise enviar em XML. Em resumo, se seu aplicativo Android quiser aproveitar a Internet, você provavelmente vai precisar trabalhar com XML. Felizmente, há várias opções disponíveis para trabalhar com XML em Android.


Analisadores XML

Acrônimos usados frequentemente

  • API: Application programming interface, ou Interface de programação de aplicativos
  • RSS: Really Simple Syndication, ou Organização Bem Simples
  • SDK: Software Developers Kit, ou Kit para Desenvolvedores de Software
  • UI: User interface, ou Interface com o Usuário
  • URL: Universal Resource Locator, ou Localizador de Recurso Universal
  • XML: Extensible Markup Language, ou Linguagem de Marcação Extensível

Um dos pontos mais fortes da plataforma Android é que ela aproveita a linguagem de programação Java. O Android SDK não oferece tudo o que está disponível no seu Java Runtime Environment (JRE) padrão, mas dá suporte a uma parte bem significativa dos seus recursos. Já há algum tempo, a plataforma Java tem suporte para muitos modos diferentes de trabalhar com XML, e a maioria dos APIs Java relacionados a XML tem suporte total no Android. Por exemplo, Simple API for XML (SAX) do Java e o Document Object Model (DOM) estão disponíveis em Android. Esses dois APIs fazem parte da tecnologia Java há muitos anos. O Streaming API for XML (StAX), mais recente, não está disponível no Android. Contudo, o Android fornece uma biblioteca de funcionalidade equivalente. Por fim, o Java XML Binding API também não está disponível no Android. Esse API sem dúvida poderia ser implementado no Android. Contudo, ele tende a ser muito pesado, e geralmente são necessárias muitas instâncias de muitas classes diferentes para representar um documento XML. Assim, é menos ideal para um ambiente restrito como os dispositivos portáteis nos quais o Android foi projetado para ser executado. Nas seções a seguir, vamos pegar uma fonte simples de XML disponível na Internet e ver como analisá-la dentro do aplicativo Android usando os vários APIs mencionados acima. Primeiro, analise as partes essenciais do aplicativo simples que usará o XML na Internet.


Leitor de notícias em Android

O aplicativo vai pegar um feed RSS do popular site de desenvolvedor do Android, o Androidster, e analisá-lo em uma lista de objetos Java simples que você pode usar em apoio a um Android ListView (veja em Downloads o código de origem). Esse é um comportamento polimórfico clássico, — diferentes implementações (diferentes algoritmos de análise XML) que fornecem o mesmo comportamento. A Listagem 1 mostra como é fácil modelar isso em código Java usando uma interface.

Listagem 1. Interface do analisador de feed XML
package org.developerworks.android;
import java.util.List;

public interface FeedParser {
    List<Message> parse();
}

Em Listagem 2, a classe Mensagem é um Plain Old Java Object (POJO) clássico que representa uma estrutura de dados.

Listagem 2. A Mensagem POJO
                public class Message implements Comparable<Message>{
				    static SimpleDateFormat FORMATTER =
		new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
			    private String title;
			    private URL link;
			    private String description;
			    private Date date;
		
			   // getters and setters omitted for brevity
			    public void setLink(String link) {
			        try {
			            this.link = new URL(link);
				    } catch (MalformedURLException e) {
			            throw new RuntimeException(e);
			        }
			    }
			    public String getDate() {
			        return FORMATTER.format(this.date);
			    }
			    public void setDate(String date) {
			        // pad the date if necessary
			        while (!date.endsWith("00")){
			            date += "0";
			        }
			        try {
			            this.date = FORMATTER.parse(date.trim());
			        } catch (ParseException e) {
			            throw new RuntimeException(e);
			        }
			    }
	
				@Override
			    public String toString() {
		             // omitted for brevity
			    }
			
				 @Override
			    public int hashCode() {
		            // omitted for brevity
			    }
		
				@Override
			    public boolean equals(Object obj) {
		            // omitted for brevity
			    }
			      // sort by date
			    public int compareTo(Message another) {
			        if (another == null) return 1;
			        // sort descending, most recent first
			        return another.date.compareTo(date);
				}
			}

Mensagem, na Listagem 2, é bem simples. Ela oculta parte de seu estado interno permitindo que datas e links sejam acessados como cadeias de caracteres simples, enquanto as representam como objetos de tipo mais forte (java.util.Date e java.net.URL). É um Value Object clássico e que, portanto, implementa equals() e hashCode() com base em seu estado interno. Ele implementa também a interface Comparável, que você pode usar para classificação (por data). Na prática, os dados sempre vêm classificados do feed, de modo que isso não é necessário.

Cada uma das implementações do analisador precisarão levar uma URL para o feed Androidster e usá-la para abrir uma conexão HTTP com o site Androidster. Esse comportamento comum é modelado naturalmente em código Java usando uma classe base abstrata como na Listagem 3.

Listagem 3. Classe base analisadora de feed
public abstract class BaseFeedParser implements FeedParser {

    // names of the XML tags
    static final String PUB_DATE = "pubDate";
    static final  String DESCRIPTION = "description";
    static final  String LINK = "link";
    static final  String TITLE = "title";
    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);
        }
    }
}

A classe base armazena o feedUrl e o usa para abrir java.io.InputStream. Se alguma coisa der errado, ele simplesmente emite uma RuntimeException, para que o aplicativo apresente uma falha rapidamente. A classe base também define algumas constantes simples para os nomes das tags. A Listagem 4 mostra conteúdo de amostra do feed, para que você veja o significado dessas tags.

Listagem 4. Amostra de feed XML
<?xml version="1.0" encoding="UTF-8"?> 
                <!-- generator="FeedCreator 1.7.2" -->
                 <rss version="2.0">
    
  <channel>
        
    <title>android_news</title>
           
    <description>android_news</description>
        
    <link>http://www.androidster.com/android_news.php</link>
        
    <lastBuildDate>Sun, 19 Apr 2009 19:43:45 +0100</lastBuildDate>
        
    <generator>FeedCreator 1.7.2</generator>
        
    <item>
           
<title>
Samsung S8000 para Executar o Android, Reproduzir DivX, Dominar o Mundo
</title>
             
      <link>http://www.androidster.com/android_news/samsung-s8000-to-run-android-
play-divx-take-over-the-world</link>
            
      <description>
Surgiram mais detalhes no primeiro telefone portátil para executar 
o Android. Um telefone celular ainda não anunciado chamado de S8000 está sendo 
divulgado ...</description>
            
      <pubDate>Thu, 16 Apr 2009 07:18:51 +0100</pubDate>
        
    </item>
        
    <item>
            
      <title>Atualização do Android Cupcake Próxima</title>
            
      <link>http://www.androidster.com/android_news/android-cupcake-update-
on-the-horizon</link>
            
      <description>
Após meses de descoberta e boatosAfter months of discovery and hearsay, 
a compilação do Android que todos estavamos 
esperando está prestes a ser lançada...
</description>
            
      <pubDate>Terça-feira, 14 de abril de 2009 04h 13min 21seg +0100</pubDate>
        
    </item>
    
  </channel>

</rss>

Como você pode ver na amostra na Listagem 4, um ITEM corresponde a uma instância de Mensagem. Os nós-filhos do item (TITLE, LINK, e assim por diante) correspondem às propriedades da instância de Mensagem. Agora que você já sabe qual é a aparência do feed e tem todas as partes comuns posicionadas, vamos dar uma olhada em como analisar esse feed usando as várias tecnologias disponíveis no Android. Vamos começar com SAX.


Usando SAX

Em um ambiente Java, você muitas vezes pode usar o API SAX se quiser um analisador rápido e quiser minimizar a área de cobertura de memória do seu aplicativo. Isso o torna muito adequado para um celular que execute Android. Pode-se usar o API SAX como é encontrado no ambiente Java, sem ser preciso modificações especiais para executá-lo no Android. A Listagem 5 mostra uma implementação SAX da interface FeedParser.

Listagem 5. Implementação SAX
public class SaxFeedParser extends BaseFeedParser {

    protected SaxFeedParser(String feedUrl){
        super(feedUrl);
    }
    
    public List<Message> parse() {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        try {
            SAXParser parser = factory.newSAXParser();
            RssHandler handler = new RssHandler();
            parser.parse(this.getInputStream(), handler);
            return handler.getMessages();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } 
    }
}

Se você já usou o SAX, ele vai lhe parecer bem familiar. Como no caso de qualquer implementação SAX, a maioria dos detalhes se encontra no manipulador SAX. O manipulador recebe eventos do analisador SAX ao passar pelo documento XML. Nesse caso, você criou uma nova classe chamada RssHandler e a registrou como manipulador do analisador, como na Listagem 6.

Listagem 6. Manipulador SAX
import static org.developerworks.android.BaseFeedParser.*;

public class RssHandler extends DefaultHandler{
    private List<Message> messages;
    private Message currentMessage;
    private StringBuilder builder;
    
    public List<Message> 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(TITLE)){
                currentMessage.setTitle(builder.toString());
            } else if (localName.equalsIgnoreCase(LINK)){
                currentMessage.setLink(builder.toString());
            } else if (localName.equalsIgnoreCase(DESCRIPTION)){
                currentMessage.setDescription(builder.toString());
            } else if (localName.equalsIgnoreCase(PUB_DATE)){
                currentMessage.setDate(builder.toString());
            } else if (localName.equalsIgnoreCase(ITEM)){
                messages.add(currentMessage);
            }
            builder.setLength(0);    
        }
    }

    @Override
    public void startDocument() throws SAXException {
        super.startDocument();
        messages = new ArrayList<Message>();
        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(ITEM)){
            this.currentMessage = new Message();
        }
    }
}

A classe RssHandler estende a classe org.xml.sax.helpers.DefaultHandler. Essa classe fornece implementações padrão e não operacionais para todos os métodos que correspondem aos eventos trazidos pelo analisador SAX. Isso permite que as subclasses apenas substituam os métodos conforme a necessidade. O RssHandler tem um API adicional, o getMessages. Ele retorna a lista de objetos Mensagem que o manipulador coleta ao receber eventos do analisador SAX. Tem duas variáveis internas, uma currentMessage para a instância de Mensagem que está sendo analisada e uma variável a StringBuilder chamada builder que armazena dados de caractere de nós de texto. Ambos são inicializados quando o método startDocument é invocado quando o analisador envia o evento correspondente ao manipulador.

Dê uma olhada no método startElement na Listagem 6. Ele é chamado toda vez que é encontrada uma tag de abertura no documento XML. Você só precisa ter cuidado quando a tag é ITEM. Nesse caso você cria uma nova Mensagem. Agora veja o método characters. Ele é chamado quando são encontrados os dados de caractere dos nós de texto. Os dados são simplesmente adicionados à variável builder. Por fim, veja o método endElement. Ele é chamado quando é encontrada uma tag de fim. Para as tags correspondentes às propriedades de uma Mensagem, como TITLE e LINK, a propriedade adequada é configurada em currentMessage usando dados da variável builder. Se a tag de fim é um ITEM, currentMessage é adicionada à lista de Mensagens. Tudo isso é análise de SAX bem típica; nada disso é exclusivo do Android. Então, se você sabe escrever um analisador Java SAX, sabe escrever também um analisador Android SAX. Contudo, o Android SDK inclui alguns recursos convenientes no SAX.


Análise SAX mais fácil

O Android SDK contém uma classe de utilitário chamada android.util.Xml. A Listagem 7 mostra como configurar um analisador SAX com a mesma classe de utilitário.

Listagem 7. Analisador SAX no Android
public class AndroidSaxFeedParser extends BaseFeedParser {

    public AndroidSaxFeedParser(String feedUrl) {
        super(feedUrl);
    }

    public List<Message> parse() {
        RssHandler handler = new RssHandler();
        try {
            Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8, handler);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return handler.getMessages();
    }

}

Note que essa classe ainda usa o manipulador SAX padrão, de modo que basta reutilizar o RssHandler mostrado acima, na Listagem 7. Ser capaz de reutilizar o manipulador SAX é ótimo, mas é um trecho de código um tanto complicado. Como dá para imaginar, se fosse preciso analisar um documento XML muito mais complexo, o manipulador poderia virar um "criadouro" de erros. Por exemplo, dê uma olhada novamente no método endElement na Listagem 6. Notou como ele verifica se o currentMessage é nulo antes de tentar determinar as propriedades? Agora dê uma olhada novamente no XML de amostra na Listagem 4. Note que há tags TITLE e LINK fora das tags ITEM. Foi por isso que foi incluída a verificação de nulo. Senão, a primeira tag TITLE poderia causar uma NullPointerException. O Android inclui sua própria variante de API SAX (veja a Listagem 8) que elimina a necessidade de você escrever seu próprio manipulador SAX.

Listagem 8. Analisador SAX simplificado no Android
public class AndroidSaxFeedParser extends BaseFeedParser {

    public AndroidSaxFeedParser(String feedUrl) {
        super(feedUrl);
    }

    public List<Message> parse() {
        final Message currentMessage = new Message();
        RootElement root = new RootElement("rss");
        final List<Message> messages = new ArrayList<Message>();
        Element channel = root.getChild("channel");
        Element item = channel.getChild(ITEM);
        item.setEndElementListener(new EndElementListener(){
            public void end() {
                messages.add(currentMessage.copy());
            }
        });
        item.getChild(TITLE).setEndTextElementListener(new EndTextElementListener(){
            public void end(String body) {
                currentMessage.setTitle(body);
            }
        });
        item.getChild(LINK).setEndTextElementListener(new EndTextElementListener(){
            public void end(String body) {
                currentMessage.setLink(body);
            }
        });
        item.getChild(DESCRIPTION).setEndTextElementListener(new 
EndTextElementListener(){
            public void end(String body) {
                currentMessage.setDescription(body);
            }
        });
        item.getChild(PUB_DATE).setEndTextElementListener(new EndTextElementListener(){
            public void end(String body) {
                currentMessage.setDate(body);
            }
        });
        try {
            Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8, 
root.getContentHandler());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return messages;
    }
}

Como prometido, o novo código de análise SAX não usa um manipulador SAX. Em vez disso, ele usa classes do pacote android.sax no SDK. Elas permitem que você modele a estrutura do seu documento XML e inclua um listener de evento conforme a necessidade. No código acima, você declara que seu documento terá um elemento-raiz chamado rss e que esse elemento terá um elemento-filho chamado channel. Depois, diz que o channel terá um elemento-filho chamado ITEM e começa a anexar listeners. Para cada listener, foi usada uma classe interna anônima que implementou a interface na qual você estava interessado (EndElementListner ou EndTextElementListener). Note que não foi necessário acompanhar os dados de caractere. Isso não só é mais simples, mas, na verdade, é mais eficiente. Por fim, quando invoca o método de utilitário Xml.parse, você passa um manipulador que é gerado a partir do elemento-raiz.

Todo código acima na Listagem 8 é opcional. Se você prefere o código de análise padrão do SAX no ambiente Java, pode usá-lo. Se quiser experimentar os wrappers convenientes fornecidos pelo Android SDK, pode usá-los também. E se você não quiser usar o SAX? Há algumas alternativas. A primeira que veremos é o DOM.


Trabalhando com DOM

A análise DOM tem suporte total no Android. Ela funciona exatamente como no código Java que você executaria em uma máquina desktop ou em um servidor. A Listagem 9 mostra uma implementação baseada em DOM da interface de analisador.

Listagem 9. Implementação baseada em DOM do analisador de feed
public class DomFeedParser extends BaseFeedParser {

    protected DomFeedParser(String feedUrl) {
        super(feedUrl);
    }

    public List<Message> parse() {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        List<Message> messages = new ArrayList<Message>();
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document dom = builder.parse(this.getInputStream());
            Element root = dom.getDocumentElement();
            NodeList items = root.getElementsByTagName(ITEM);
            for (int i=0;i<items.getLength();i++){
                Message message = new Message();
                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.setDate(property.getFirstChild().getNodeValue());
                    }
                }
                messages.add(message);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } 
        return messages;
    }
}

Como no primeiro exemplo de SAX, não há nada específico do Android nesse código. O analisador DOM lê todo o documento XML na memória e depois lhe permite usar os APIs DOM para percorrer a árvore XML, recuperando os dados desejados. É um código bem simples e, em certos aspectos, até mais simples que as implementações baseadas em SAX. Contudo, o DOM em geral consome mais memória, visto que tudo é lido primeiro na memória. Isso pode ser um problema em celulares que executam Android, mas é satisfatório em certos casos de uso em que o documento XML não é muito grande. Dá para chegar à conclusão de que os desenvolvedores do Android acharam que a análise SAX seria muito mais comum em aplicativos Android, em vista dos utilitários extras que forneceram para ela. Há outro tipo de analisador XML disponível no Android: o analisador pull.


Analisador pull de XML

Como já mencionado, o Android não fornece suporte para a API StAX do Java. Contudo, o Android vem com um analisador pull que funciona de forma parecida ao StAX. Ele permite que seu código de aplicativo puxe ou procure eventos do analisador, ao contrário do analisador SAX que empurra automaticamente eventos para o manipulador. A Listagem 10 mostra uma implementação de analisador pull da interface do analisador de feed.

Listagem 10. Implementação baseada em analisador pull
public class XmlPullFeedParser extends BaseFeedParser {
    public XmlPullFeedParser(String feedUrl) {
        super(feedUrl);
    }
    public List<Message> parse() {
        List<Message> messages = null;
        XmlPullParser parser = Xml.newPullParser();
        try {
            // auto-detect the encoding from the stream
            parser.setInput(this.getInputStream(), null);
            int eventType = parser.getEventType();
            Message currentMessage = null;
            boolean done = false;
            while (eventType != XmlPullParser.END_DOCUMENT && !done){
                String name = null;
                switch (eventType){
                    case XmlPullParser.START_DOCUMENT:
                        messages = new ArrayList<Message>();
                        break;
                    case XmlPullParser.START_TAG:
                        name = parser.getName();
                        if (name.equalsIgnoreCase(ITEM)){
                            currentMessage = new Message();
                        } else if (currentMessage != null){
                            if (name.equalsIgnoreCase(LINK)){
                                currentMessage.setLink(parser.nextText());
                            } else if (name.equalsIgnoreCase(DESCRIPTION)){
                                currentMessage.setDescription(parser.nextText());
                            } else if (name.equalsIgnoreCase(PUB_DATE)){
                                currentMessage.setDate(parser.nextText());
                            } else if (name.equalsIgnoreCase(TITLE)){
                                currentMessage.setTitle(parser.nextText());
                            }    
                        }
                        break;
                    case XmlPullParser.END_TAG:
                        name = parser.getName();
                        if (name.equalsIgnoreCase(ITEM) && 
currentMessage != null){
                            messages.add(currentMessage);
                        } else if (name.equalsIgnoreCase(CHANNEL)){
                            done = true;
                        }
                        break;
                }
                eventType = parser.next();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return messages;
    }
}

O analisador pull funciona de forma semelhante ao analisador SAX. Ele tem eventos similares (elemento inicial, elemento final), mas é preciso puxar deles (parser.next()). Os eventos são enviados como códigos numéricos, de modo que se pode usar um case-switch simples. Note que, em vez de ouvir o fim dos elementos em uma análise SAX, com a análise pull é simples executar a maior parte do processamento no início. No código da Listagem 10, quando um elemento inicia, é possível chamar parser.nextText() para puxar todos os dados de caractere do documento XML. Isso permite uma ótima simplificação em relação à análise SAX. Note também que você determinou um sinalizador (a variável booleana done) para identificar quando foi atingido o fim do conteúdo que lhe interessa. Isso permite que você interrompa a leitura do documento XML mais cedo, visto que sabe que o código não vai se importar com o restante do documento. Isso pode ser bem útil, em especial se você só precisa de uma pequena parte do documento XML que está sendo acessado. É possível reduzir muito o tempo de análise interrompendo-a assim que possível. Novamente, esse tipo de otimização é especialmente importante em celulares em que a velocidade da conexão pode ser baixa. O analisador pull pode ter algumas ótimas vantagens de desempenho, bem como facilidade de uso. Também pode ser usado para escrever XML.


Criando XML

Até agora, nós nos concentramos em analisar XML a partir da Internet. Contudo, às vezes seu aplicativo pode precisar enviar XML para um servidor remoto. É óbvio que você pode apenas usar o StringBuilder ou algo similar para criar uma cadeia de caracteres XML. Outra alternativa é o analisador pull da Listagem 11.

Listagem 11. Escrevendo XML com analisador pull
private String writeXml(List<Message> messages){
    XmlSerializer serializer = Xml.newSerializer();
    StringWriter writer = new StringWriter();
    try {
        serializer.setOutput(writer);
        serializer.startDocument("UTF-8", true);
        serializer.startTag("", "messages");
        serializer.attribute("", "number", String.valueOf(messages.size()));
        for (Message msg: messages){
            serializer.startTag("", "message");
            serializer.attribute("", "date", msg.getDate());
            serializer.startTag("", "title");
            serializer.text(msg.getTitle());
            serializer.endTag("", "title");
            serializer.startTag("", "url");
            serializer.text(msg.getLink().toExternalForm());
            serializer.endTag("", "url");
            serializer.startTag("", "body");
            serializer.text(msg.getDescription());
            serializer.endTag("", "body");
            serializer.endTag("", "message");
        }
        serializer.endTag("", "messages");
        serializer.endDocument();
        return writer.toString();
    } catch (Exception e) {
        throw new RuntimeException(e);
    } 
}

A classe XmlSerializer faz parte do mesmo pacote do XmlPullParser usado na seção anterior. Em vez de puxar eventos, ela os empurra para um fluxo ou um gravador. Nesse caso ele simplesmente os empurra para uma instância java.io.StringWriter. Ele fornece um API simples com métodos para iniciar e terminar um documento, processar elementos e adicionar texto ou atributos. Essa pode ser uma boa alternativa ao uso do StringBuilder, visto que é mais fácil assegurar que o seu XML está bem formado.


Resumo

Que tipo de aplicativo você deseja criar para dispositivos Android? Não importa qual seja, se ele precisar trabalhar com dados da Internet, provavelmente vai precisar trabalhar com XML. Neste artigo, você viu que o Android vem com várias ferramentas para lidar com XML. Você pode escolher só uma dessas como sua ferramenta preferida, ou pode escolhê-las com base no caso de uso. Na maioria das vezes o mais seguro é escolher o SAX, e o Android lhe permite tanto o modo tradicional de usar o SAX e um wrapper muito bom e conveniente para usar com o SAX. Se o seu documento for pequeno, talvez o DOM seja o mais simples de usar. Se seu documento for grande, mas você só precisar de parte dele, o analisador pull de XML pode ser um modo mais eficiente. Por fim, para escrever XML, o pacote do analisador pull fornece um modo conveniente de fazer isso também. Assim, não importam quais sejam suas necessidades no que se refere a XML, o Android SDK tem o que você precisa.


Download

DescriçãoNomeTamanho
Código de amostraAndroidXml.zip70KB

Recursos

Aprender

Obter produtos e tecnologias

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Software livre
ArticleID=406788
ArticleTitle=Trabalhando com XML no Android
publish-date=06232009