XStream me dando dor de cabeça para ler XML

4 respostas
R

Pessoal,

Estou usando o XStream para ler um XML relativamente muito fácil. Implementei todos os beans e para criar o XML a partir dos JavaBeans criados, fuinciona perfeitamente. Porém, quando eu tenho o XML obtido externamente, ele da um erro muito louco. Já vasculhei o Google para ver se alguém tinha passado por isso, e acabei não achando nada. Estou recorrendo a vocês para ver se alguém já enfrentou algo parecido com isso.

Bom vamos lá. O XML que eu tenho que ler é o da API do Twitter. É igual a esse abaixo:

<?xml version="1.0" encoding="UTF-8"?>
<statuses type="array">
<status>
  <created_at>Tue Mar 24 23:15:16 +0000 2009</created_at>
  <id>[telefone removido]</id>
  <text>zzzzzZZZzzzzz zzz ZZZZzzzzzz.  ZzzZzzzzzzzZzzzz. Zzzzz zz.   Zzzzz</text>
  <source>&lt;a href=&quot;http://www.atebits.com/software/tweetie/&quot;&gt;Tweetie&lt;/a&gt;</source>

  <truncated>false</truncated>
  <in_reply_to_status_id></in_reply_to_status_id>
  <in_reply_to_user_id></in_reply_to_user_id>
  <favorited>false</favorited>
  <in_reply_to_screen_name></in_reply_to_screen_name>
  <user>
    <id>16428990</id>

    <name>Alex </name>
    <screen_name>Xlex</screen_name>
    <location>Amsterdam</location>
    <description>Hi ! I'm Alex . Im an artist , designer , and a musician. Oh and i LOVE to twittt !!!!!!!!</description>
    <profile_image_url>http://s3.amazonaws.com/twitter_production/profile_images/61499379/photo-3c_normal.JPG</profile_image_url>
    <url></url>

    <protected>false</protected>
    <followers_count>583</followers_count>
  </user>
</status>
<status>
  <created_at>Tue Mar 24 23:14:50 +0000 2009</created_at>
  <id>[telefone removido]</id>
  <text>Going to sleep, feeling so lonely :( so diprest. SleepSweet Twitterrrr !</text>

  <source>&lt;a href="http://www.atebits.com/software/tweetie/"&gt;Tweetie&lt;/a&gt;</source>
  <truncated>false</truncated>
  <in_reply_to_status_id></in_reply_to_status_id>
  <in_reply_to_user_id></in_reply_to_user_id>
  <favorited>false</favorited>
  <in_reply_to_screen_name></in_reply_to_screen_name>

  <user>
    <id>16428990</id>
    <name>Alex </name>
    <screen_name>Xlex</screen_name>
    <location>Amsterdam</location>
    <description>Hi ! I'm Alex . Im an artist , designer , and a musician. Oh and i LOVE to twittt !!!!!!!!</description>

    <profile_image_url>http://s3.amazonaws.com/twitter_production/profile_images/61499379/photo-3c_normal.JPG</profile_image_url>
    <url></url>
    <protected>false</protected>
    <followers_count>583</followers_count>
  </user>
</status>
<status>
  <created_at>Tue Mar 24 22:14:10 +0000 2009</created_at>

  <id>[telefone removido]</id>
  <text>Vai nessa, monkey boy: http://tinyurl.com/c4v65s</text>
  <source>&lt;a href="http://twitterfox.net/"&gt;TwitterFox&lt;/a&gt;</source>
  <truncated>false</truncated>
  <in_reply_to_status_id></in_reply_to_status_id>
  <in_reply_to_user_id></in_reply_to_user_id>

  <favorited>false</favorited>
  <in_reply_to_screen_name></in_reply_to_screen_name>
  <user>
    <id>8524192</id>
    <name>Eust&#225;quio Rangel</name>
    <screen_name>taq</screen_name>

    <location>S&#227;o Jos&#233; do Rio Preto, SP, Bra</location>
    <description>http://eustaquiorangel.com/me</description>
    <profile_image_url>http://s3.amazonaws.com/twitter_production/profile_images/56074459/taqblack_normal.jpg</profile_image_url>
    <url>http://eustaquiorangel.com</url>
    <protected>false</protected>

    <followers_count>456</followers_count>
  </user>
</status>
</statuses>
Meus Beans estão implementados assim:
package com.jforbidtwitt.xml.beans;

import java.util.ArrayList;
import java.util.List;

public class Statuses {
	
	private String type;
	private List<Status> status = new ArrayList<Status>();
	
	public String getType() {
		return type;
	}
	
	public void setType(String type) {
		this.type = type;
	}
	
	public void add(Status status) {
		this.status.add(status);
	}
	
	public List<Status> getContent() {
		return this.status;
	}
}
package com.jforbidtwitt.xml.beans;

public class Status {
	
	private String created_at;
	private String id;
	private String text;
	private String source;
	private boolean truncated;
	private String in_reply_to_status_id;
	private String in_reply_to_user_id;
	private boolean favorited;
	private String in_reply_to_screen_name;
	private User user;
	
	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public String getCreated_at() {
		return created_at;
	}
	
	public void setCreated_at(String created_at) {
		this.created_at = created_at;
	}
	
	public String getId() {
		return id;
	}
	
	public void setId(String id) {
		this.id = id;
	}
	
	public String getText() {
		return text;
	}
	
	public void setText(String text) {
		this.text = text;
	}
	
	public String getSource() {
		return source;
	}
	
	public void setSource(String source) {
		this.source = source;
	}
	
	public boolean isTruncated() {
		return truncated;
	}
	
	public void setTruncated(boolean truncated) {
		this.truncated = truncated;
	}
	
	public String getIn_reply_to_status_id() {
		return in_reply_to_status_id;
	}
	
	public void setIn_reply_to_status_id(String in_reply_to_status_id) {
		this.in_reply_to_status_id = in_reply_to_status_id;
	}
	
	public String getIn_reply_to_user_id() {
		return in_reply_to_user_id;
	}
	
	public void setIn_reply_to_user_id(String in_reply_to_user_id) {
		this.in_reply_to_user_id = in_reply_to_user_id;
	}
	
	public boolean isFavorited() {
		return favorited;
	}
	
	public void setFavorited(boolean favorited) {
		this.favorited = favorited;
	}
	
	public String getIn_reply_to_screen_name() {
		return in_reply_to_screen_name;
	}
	
	public void setIn_reply_to_screen_name(String in_reply_to_screen_name) {
		this.in_reply_to_screen_name = in_reply_to_screen_name;
	}
}
package com.jforbidtwitt.xml.beans;

public class User {

	private String name;
	private String screen_name;
	private String location;
	private String description;
	private String profile_image_url;
	private String url;
	private boolean protect;
	private int followers_count;
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public String getScreen_name() {
		return screen_name;
	}
	
	public void setScreen_name(String screen_name) {
		this.screen_name = screen_name;
	}
	
	public String getLocation() {
		return location;
	}
	
	public void setLocation(String location) {
		this.location = location;
	}
	
	public String getDescription() {
		return description;
	}
	
	public void setDescription(String description) {
		this.description = description;
	}
	
	public String getProfile_image_url() {
		return profile_image_url;
	}
	
	public void setProfile_image_url(String profile_image_url) {
		this.profile_image_url = profile_image_url;
	}
	
	public String getUrl() {
		return url;
	}
	
	public void setUrl(String url) {
		this.url = url;
	}
	
	public boolean isProtect() {
		return protect;
	}
	
	public void setProtect(boolean protect) {
		this.protect = protect;
	}
	
	public int getFollowers_count() {
		return followers_count;
	}
	
	public void setFollowers_count(int followers_count) {
		this.followers_count = followers_count;
	}
}

E para ler o XML estou fazendo assim:

package com.jforbidtwitt.xml;

import com.jforbidtwitt.xml.beans.Status;
import com.jforbidtwitt.xml.beans.Statuses;
import com.jforbidtwitt.xml.beans.User;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

public class XMLRead {
	
	public static Statuses readXML(String xml) {
		System.out.println();
		XStream xs = new XStream(new DomDriver());
		xs.alias("statuses", Statuses.class);
		xs.alias("status", Status.class);
		xs.alias("user", User.class);
		xs.aliasAttribute(Statuses.class, "type", "type");
		xs.addImplicitCollection(Statuses.class, "status");
		xs.aliasField("protect", User.class, "protected");
		
		Statuses res = (Statuses) xs.fromXML(xml);
		System.out.println(res);
		
		return res;
	}
}

E finalmente, porém muito importante, o erro cabuloso que o XStream gera:

Exception in thread "main" com.thoughtworks.xstream.converters.ConversionException: created_at : created_at : created_at : created_at ---- Debugging information ---- message : created_at : created_at cause-exception : com.thoughtworks.xstream.mapper.CannotResolveClassException cause-message : created_at : created_at class : com.jforbidtwitt.xml.beans.Statuses required-type : java.lang.Object path : /statuses/status/created_at ------------------------------- at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:89) at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:63) at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:76) at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:60) at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:225) at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:162) at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:82) at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:63) at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:76) at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:60) at com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:137) at com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.unmarshal(AbstractTreeMarshallingStrategy.java:33) at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:923) at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:909) at com.thoughtworks.xstream.XStream.fromXML(XStream.java:853) at com.thoughtworks.xstream.XStream.fromXML(XStream.java:845) at com.jforbidtwitt.xml.XMLRead.readXML(XMLRead.java:21) at com.jforbidtwitt.main.Main.main(Main.java:22) Caused by: com.thoughtworks.xstream.mapper.CannotResolveClassException: created_at : created_at at com.thoughtworks.xstream.mapper.DefaultMapper.realClass(DefaultMapper.java:68) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) at com.thoughtworks.xstream.mapper.DynamicProxyMapper.realClass(DynamicProxyMapper.java:71) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) at com.thoughtworks.xstream.mapper.PackageAliasingMapper.realClass(PackageAliasingMapper.java:88) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) at com.thoughtworks.xstream.mapper.ClassAliasingMapper.realClass(ClassAliasingMapper.java:86) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) at com.thoughtworks.xstream.mapper.ArrayMapper.realClass(ArrayMapper.java:96) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) at com.thoughtworks.xstream.mapper.CachingMapper.realClass(CachingMapper.java:52) at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.determineType(AbstractReflectionConverter.java:347) at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:208) at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:162) at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:82) ... 17 more

Alguém consegue ter alguma luz nesse túnel sombrio?

Obrigado

4 Respostas

R

Só atualizando o post. Como eu não consegui ainda usar o XStream para ler essa XML, fui para o JDOM mesmo e fiz o parse “manual”. Funcionou muito bem o método que implementei pra realizar o parser usando o JDOM. Abaixo está o método implementado usando o JDOM. Mas mesmo assim, que souber como arrumar o erro do XStream, por favor, eu ainda gostaria de usar o XStream.

public class JDOMRead implements XMLRead {

	@SuppressWarnings("unchecked")
	@Override
	public Statuses readXML(String XML) throws NullXMLException {
		
		if (XML == null) {
			throw new NullXMLException("A XML passada como parâmetro não pode ser nula.");
		}
		
		SAXBuilder parser = new SAXBuilder();
        
        try {
            Document doc = parser.build(new StringReader(XML));
            Element root = doc.getRootElement();
            List<Element> status = root.getChildren("status");

            Iterator<Element> i = status.iterator();

            Statuses statuses = new Statuses();
            Status st = null;
            User user = null;

            while(i.hasNext()) {
                Element s = i.next();
                st = new Status();

                st.setCreated_at(s.getChildText("created_at"));
                st.setFavorited(Boolean.parseBoolean(s.getChildText("favorited")));
                st.setId(s.getChildText("id>"));
                st.setIn_reply_to_screen_name(s.getChildText("in_reply_to_screen_name"));
                st.setIn_reply_to_user_id(s.getChildText("in_reply_to_user_id"));
                st.setIn_reply_to_status_id(s.getChildText("in_reply_to_status_id"));
                st.setSource(s.getChildText("source"));
                st.setText(s.getChildText("text"));
                st.setTruncated(Boolean.parseBoolean(s.getChildText("truncated")));

                user = new User();
                user.setDescription(s.getChild("user").getChildText("description"));
                user.setFollowers_count(Integer.parseInt(s.getChild("user").getChildText("followers_count")));
                user.setId(s.getChild("user").getChildText("id"));
                user.setLocation(s.getChild("user").getChildText("location"));
                user.setName(s.getChild("user").getChildText("name"));
                user.setProfile_image_url(s.getChild("user").getChildText("profile_image_url"));
                user.setProtect(Boolean.parseBoolean(s.getChild("user").getChildText("protected")));
                user.setScreen_name(s.getChild("user").getChildText("screen_name"));
                user.setUrl(s.getChild("user").getChildText("url"));

                st.setUser(user);

                statuses.add(st);
            }

            return statuses;

        }
        catch (JDOMException e) {
            e.printStackTrace();
            return null;
        }
        catch (IOException e) {
            e.printStackTrace();
            return null;
        }
	}
}
R

Mais de 1 ano depois, mas está aí caso possa ajudar alguém:

Quem faz a mágica é a classe “XmlFriendlyReplacer”.

J

Em situação igual a deste problema, um “conflito” foi resolvido quando modifiquei em meu código o equivalente ao nome do atributo e status (em seu codigo) para algo diferente do alias da classe. Ou seja, escolha um nome diferente para o atributo status da classe Statuses (linha 09) não esquecendo de atualizar tambem na linha 18 da classe XMLRead.

A

Tive um problema semelhante. A solução que apliquei foi utilizar a anotação “@XStreamImplicit”:

public class Statuses {

private String type;  

@XStreamImplicit
private List<Status> status = new ArrayList<Status>();
Criado 24 de março de 2009
Ultima resposta 9 de jul. de 2014
Respostas 4
Participantes 4