¿Cómo analizar XML y almacenarlo en un mapa con SimpleXML?
Tengo problemas para analizar xml con un marco xml simple. Quiero almacenar id de categoría y lista de torneos dentro de un mapa / hashMap ¿cómo puedo hacer eso? He seguido el tutorial en xml simple, pero no funciona para mí.
Lo guardé en una lista como esta:
- Retrofit y SimpleXML para el elemento raíz desconocido?
- Excepción ValueRequired mientras utiliza Simple-XML-Framework
- Usando SimpleXML, cómo ignorar elementos xml que no tengo en mi clase de objeto al deserializar
- ¿Cómo usar Retrofit y SimpleXML juntos para descargar y analizar un archivo XML de un sitio?
- Error de deserialización de SimpleXML en Android
@ElementList(entry = "Category", inline = true, required = false) List<Category> category;
Pero ahora quiero guardarlo en un mapa.
Aquí está xml:
Tutorial que seguí:
Cualquier ayuda sería apreciada, tnx.
- Android, simple-xml, cómo declarar una lista de elementos?
- Android Retrofit 2 Simple XML Converter
- Simple XML analiza XML a la lista
- SimpleXML con Retrofit 1.9, 'Atributo' versión 'no tiene una coincidencia en la clase'
- Eliminar el atributo class =
- Problemas al integrar el convertidor Simple XML en retrofit para Android
- Analizar elementos de la lista de archivos XML con XML simple en Android
- Saco de jabón de marco simple y cuerpo
No es posible por Annoations como @ElementList
o @ElementMap
, pero usar un Converter
sigue siendo una opción (buena) .
El ir de esa manera significa: Implementar un convertidor para Tournaments
que fusiona el par de la categoría-Id / lista de torneos.
Y aquí es cómo se hace esto:
Primero las clases (datos) necesarias.
Torneo:
@Root(name = "Tournament") public class Tournament { @Text private String data; public Tournament(String data) { this.data = data; } private Tournament() { /* Required */ } // ... }
Nota: Le di al Tournament
alguna cadena de datos, ya que los datos reales no se muestran. Sin embargo, en realidad no importa los datos que contiene.
Categoría:
@Root(name = "Category") public class Category { private String id; // ... }
Torneos
@Root(name = "Tournaments") @Convert(TournamentsConverter.class) // Specify the Converter used for this class public class Tournaments { private Map<String, List<Tournament>> tournaments; public Tournaments() { tournaments = new HashMap<>(); } protected void put(String id, List<Tournament> tournaments) { this.tournaments.put(id, tournaments); } // ... }
El @Convert
utilizará el siguiente Converter
para la serialización / deserialización de los Tournaments
. No he implementado la parte de serialización en este ejemplo (no es difícil sin embargo).
Importante: @Convert
requiere una AnnotationStrategy
(ver ejemplo abajo)!
Convertidor de torneos
public class TournamentsConverter implements Converter<Tournaments> { private final Serializer serializer = new Persister(); @Override public Tournaments read(InputNode node) throws Exception { Tournaments tournaments = new Tournaments(); InputNode childNode = node.getNext(); // Iterate over all childs of 'Tournaments' while( childNode != null ) { if( childNode.getName().equals("Category") == true ) { final String categoryId = childNode.getAttribute("category_id").getValue(); List<Tournament> tournamentList = new ArrayList<>(); InputNode child = childNode.getNext(); // Iterate over all childs of 'Category' while( child != null ) { // Use a Serializer to read the nodes data Tournament tournament = serializer.read(Tournament.class, child); tournamentList.add(tournament); child = childNode.getNext(); } // Insert the Id / Tournament's pair tournaments.put(categoryId, tournamentList); } childNode = node.getNext(); } return tournaments; } @Override public void write(OutputNode node, Tournaments value) throws Exception { // Implement as needed throw new UnsupportedOperationException("Not supported yet."); } }
Toda la "magia" es hecha por el Convertidor:
- Iterate sobre todos los nodos secundarios de los
Tournaments
- Si es una
Category
- Obtener el
id
- Iterate sobre todos los niños y agregue el
Tournament
a una lista - Agregue la
id
/ lista deTournament
a losTournaments
resultados
- Obtener el
Como se muestra arriba, es posible utilizar un Serializer
para (des) serialización de nodos. No hay necesidad de implementarlo a mano.
Ejemplo
Por último, he aquí un ejemplo. Tenga en cuenta la AnnotationStrategy
.
Serializer ser = new Persister(new AnnotationStrategy()); final String xml = "<Tournaments>\n" + " <Category category_id=\"289\">\n" + " <Tournament>aaaa</Tournament>\n" + " </Category>\n" + " <Category category_id=\"32\">\n" + " <Tournament>bbbd</Tournament>\n" + " <Tournament>cccc</Tournament>\n" + " </Category>\n" + "</Tournaments>"; Tournaments t = ser.read(Tournaments.class, xml); System.out.println(t);
Salida:
Usando generado toString()
agregado a cada clase.
Tournaments{tournaments={289=[Tournament{data=aaaa}], 32=[Tournament{data=bbbd}, Tournament{data=cccc}]}}
El problema es que está intentando crear una estructura como Map<String, <List<Tournament>>
y que no parece ser posible con la anotación ElementMap
. Necesita una clase de anotación ElementMapList
. Tal vez usted puede presentar un problema y el Sr. Gallagher puede agregar eso.