2010-10-01 11 views
4

Je ne suis pas un développeur, je fais juste de la programmation. Un domaine que je ne comprends jamais est l'analyse XML. Malheureusement, pour mon dernier "projet", j'ai besoin de faire cela même pour une application Android. C'est un prototype que je fais pour le travail.ANDROID: Analyse syntaxique XML

Je possède ce XML (fichier maquette):

<feed version="201010011221" > 
    <period from="2010-10-01T10:08:34Z" to="2010-10-01T10:08:34Z"> 
    <lines> 
     <line id="SKI" name="Ski" shortname="ski" status="1 calls queued"> 
     <calls> 
      <call id="6584" created="2010-10-01T11:22:42Z"> 
      <booking>1275243</booking> 
      </call> 
     </calls> 
     </line> 
     <line id="CRU" name="Cruise" shortname="cruise" status="0 calls queued"> 
     <calls /> 
     </line> 
     <line id="VIL" name="Villas" shortname="villas" status="2 calls queued"> 
     <calls> 
      <call id="25878" created="2010-10-01T10:22:42Z"> 
      <booking>1077244</booking> 
      </call> 
      <call id="25878" created="2010-10-01T10:22:42Z"> 
      <booking>1077244</booking> 
      </call> 
     </calls> 
     </line> 
    </lines> 
    </period> 
</feed> 

J'ai un code qui me fait un NodeList de chacun:

inputStream = OpenHttpConnection(URL); 
Document document = null; 
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); 
DocumentBuilder documentBuilder; 
documentBuilder = documentBuilderFactory.newDocumentBuilder(); 
document = documentBuilder.parse(inputStream); 
document.getDocumentElement().normalize(); 
NodeList lineNodes = document.getElementsByTagName("line"); 

Je ne sais pas quoi faire prochain. Mon code semble assez long pour cela. J'ai cherché sur google de meilleures méthodes, mais un code plus propre que j'ai trouvé, je ne pouvais pas me mettre au travail.

Existe-t-il de bons didacticiels Android pour Android? Ou quelqu'un peut-il m'aider avec ce code?

J'ai besoin d'obtenir chacun dans un HashMap où String est l'ID.

La ligne est la classe de toutes les informations affichées.

Merci Neil

+0

http://stackoverflow.com/questions/4827344/how-to-parse-xml-using-the-sax-parser – hakre

Répondre

7

Je n préférez ne pas utiliser DOM car il a une plus grande empreinte mémoire. Avec DOM, toute la structure XML est d'abord chargée en mémoire puis traitée. Ce n'est peut-être pas la meilleure solution pour le développement mobile.

Utilisez l'analyseur syntaxique SAX fourni avec Android. C'est une approche axée sur l'événement. Chaque balise de début, le contenu entre les balises et les événements d'incendie de balise de fin lorsqu'ils se produisent. En fait, il peut gérer plus d'événements, mais ce sont les événements les plus couramment utilisés. Cela signifie que l'analyseur syntaxique SAX traite chaque ligne une par une sans charger d'abord la structure XML entière en mémoire.

Je vais poster un exemple pour votre problème particulier demain.

EDIT: Voici l'exemple de gestionnaire de contenu promis.

import java.util.HashMap; 
import org.xml.sax.Attributes; 
import org.xml.sax.ContentHandler; 
import org.xml.sax.Locator; 
import org.xml.sax.SAXException; 

public class MyContentHandler implements ContentHandler { 

    private HashMap<String, Object> feed; 
    private HashMap<String, Object> peroidContent; 
    private HashMap<String, Object> callContent; 
    private HashMap<String, Object> callsMap; 
    private HashMap<String, Object> lineContent; 
    private HashMap<String, Object> linesMap; 

    private String text; 
    private String callId; 
    private String lineId; 

    @Override 
    public void startDocument() throws SAXException { 
     /* You can perform some action in this method 
     * for example to reset some sort of Collection 
     * or any other variable you want. It gets called 
     * every time a document starts. */ 
     feed = new HashMap<String, Object>(); 
    } 

    @Override 
    public void startElement(String uri, String localName, String qName, 
      Attributes atts) throws SAXException { 
     // Gets called every time an opening tag is encountered. 
     if(localName.equalsIgnoreCase("FEED")) { 
      /* We've found a "feed" opening tag so we capture its 
      * version attribute and put it into our HashMap.*/ 
      feed.put("Version", atts.getValue("version")); 
     } else if(localName.equalsIgnoreCase("PEROID")) { 
      peroidContent = new HashMap<String, Object>(); 
      peroidContent.put("From", atts.getValue("from")); 
      peroidContent.put("to", atts.getValue("to")); 
     } else if(localName.equalsIgnoreCase("LINE")) { 
      linesMap = new HashMap<String, Object>(); 
     } else if(localName.equalsIgnoreCase("LINE")) { 
      lineContent = new HashMap<String, Object>(); 
      lineId = atts.getValue("id"); 
      lineContent.put("name", atts.getValue("name")); 
      lineContent.put("shortname", atts.getValue("shortname")); 
      lineContent.put("status", atts.getValue("status")); 
     } else if(localName.equalsIgnoreCase("CALLS")) { 
      callsMap = new HashMap<String, Object>(); 
     } else if(localName.equalsIgnoreCase("CALL")) { 
      callContent = new HashMap<String, Object>(); 
      callId = atts.getValue("Id"); 
      callContent.put("created", atts.getValue("created")); 
     } 
    } 

    @Override 
    public void characters(char[] ch, int start, int length) 
      throws SAXException { 
     /* Gets called every time in between an opening tag and 
     * a closing tag if characters are encountered. */ 
     text = new String(ch, start, length); 
    } 

    @Override 
    public void endElement(String uri, String localName, String qName) 
      throws SAXException { 
     // Gets called every time a closing tag is encountered. 
     if(localName.equalsIgnoreCase("FEED")) { 
      feed.put("Peroid", peroidContent); 
     } else if(localName.equalsIgnoreCase("PEROID")) { 
      peroidContent.put("Lines", linesMap); 
     } else if(localName.equalsIgnoreCase("LINES")) { 
      linesMap.put(lineId, lineContent); 
     } else if(localName.equalsIgnoreCase("LINE")) { 
      lineContent.put("Calls", callsMap); 
     } else if(localName.equalsIgnoreCase("CALLS")) { 
      callsMap.put(callId, callContent); 
     } else if(localName.equalsIgnoreCase("BOOKING")) { 
      callContent.put("Booking", text.toString()); 
     } 
    } 

    @Override 
    public void endDocument() throws SAXException { 
     /* You can perform some action in this method 
     * for example to reset some sort of Collection 
     * or any other variable you want. It gets called 
     * every time a document end is reached. */ 
     SAXParsingFun.setHashMap(feed); 
    } 

    @Override 
    public void endPrefixMapping(String prefix) throws SAXException { 
     // TODO Auto-generated method stub 
    } 

    @Override 
    public void ignorableWhitespace(char[] ch, int start, int length) 
      throws SAXException { 
     // TODO Auto-generated method stub 
    } 

    @Override 
    public void processingInstruction(String target, String data) 
      throws SAXException { 
     // TODO Auto-generated method stub 
    } 

    @Override 
    public void setDocumentLocator(Locator locator) { 
     // TODO Auto-generated method stub 
    } 

    @Override 
    public void skippedEntity(String name) throws SAXException { 
     // TODO Auto-generated method stub 
    } 

    @Override 
    public void startPrefixMapping(String prefix, String uri) 
      throws SAXException { 
     // TODO Auto-generated method stub 
    } 
} 

Il y a beaucoup d'explications sur StackOverflow sur la façon d'analyser un fichier XML que j'ai laissé sortir et de vous montrer la partie la plus intéressante; le gestionnaire de contenu.

Maintenant, la plupart des parties intéressantes sont commentées afin que vous puissiez comprendre ce que j'essaie de faire.

J'ai implémenté l'interface ContentHandler juste pour vous montrer qu'il y a plus de méthodes disponibles, peut-être que vous en aurez besoin dans le futur. Vous pouvez toutefois étendre à partir de la classe DefaultHandler et simplement remplacer les méthodes nécessaires. Tout ce que vous faites est essentiellement de vérifier l'apparition de certaines balises et ensuite déclencher certains événements sur ce point. Si vous souhaitez conserver l'ordre des éléments dans le fichier XML, vous devez simplement utiliser un LinkedHashMap au lieu d'un HashMap.

J'espère que ça aide.

+0

Merci pour l'exemple ... ça a l'air bien et je pense que je commence à le comprendre. Eclipse n'aime pas SAXParsingFun.setHashMap (feed); J'imagine que cela ne fait pas partie de SAX mais pas clair comment réparer ... – neildeadman

+1

Oh désolé c'était ma faute. Cela fait partie d'une autre classe que j'ai utilisée pour initialiser le processus d'analyse. C'est juste un moyen d'envoyer le HashMap à l'autre classe.En fait, j'ai seulement expliqué comment fonctionne ContentHandler. –

+0

Je me demande si je peux poser une autre question à ce sujet? J'aime beaucoup la méthode que vous m'avez présentée, elle semble bien fonctionner. Cependant, après mes balises ... j'ai un autre tag que je pensais ne pas avoir besoin de mentionner. Ceci est . Si rien n'est présent, j'obtiens . Cependant, mon code échoue chaque fois qu'il atteint ces balises indépendamment des valeurs. Eclipse ouvre un autre onglet avec: "ExpatParser.startElement (String, String, String, int, int) ligne: 50" & "Source introuvable". Je ne peux pas trouver où aller aux exceptions levées ... êtes-vous en mesure d'aider? – neildeadman