Comment parsingr XML à l’aide de l’parsingur SAX

Je suis ce tutoriel .

Cela fonctionne très bien mais j’aimerais qu’il retourne un tableau avec toutes les chaînes au lieu d’une seule chaîne avec le dernier élément.

Des idees pour faire cela?

Donc, vous voulez construire un parsingur XML pour parsingr un stream RSS comme celui-ci.

  MyTitle http://myurl.com MyDescription SomeDate http://someurl.com SomeLanguage  TitleOne  http://linktoarticle.com   TitleTwo  http://linktoanotherarticle.com    

Vous pouvez maintenant utiliser deux implémentations SAX. Soit vous utilisez l’ org.xml.sax ou l’implémentation android.sax . Je vais vous expliquer les avantages et les inconvénients des deux après avoir publié un court exemple.

android.sax Implémentation

Commençons par l’implémentation d’ android.sax .

Vous devez d’abord définir la structure XML à l’aide des objects RootElement et Element .

Dans tous les cas, je travaillerais avec des POJO (Plain Old Java Objects) qui contiendraient vos données. Voici les POJO nécessaires.

Channel.java

 public class Channel implements Serializable { private Items items; private Ssortingng title; private Ssortingng link; private Ssortingng description; private Ssortingng lastBuildDate; private Ssortingng docs; private Ssortingng language; public Channel() { setItems(null); setTitle(null); // set every field to null in the constructor } public void setItems(Items items) { this.items = items; } public Items getItems() { return items; } public void setTitle(Ssortingng title) { this.title = title; } public Ssortingng getTitle() { return title; } // rest of the class looks similar so just setters and getters } 

Cette classe implémente l’interface Serializable afin que vous puissiez la mettre dans un Bundle et en faire quelque chose.

Maintenant, nous avons besoin d’une classe pour contenir nos articles. Dans ce cas, je vais juste étendre la classe ArrayList .

Items.java

 public class Items extends ArrayList { public Items() { super(); } } 

Thats it pour notre conteneur d’articles. Nous avons maintenant besoin d’une classe pour contenir les données de chaque élément.

Item.java

 public class Item implements Serializable { private Ssortingng title; private Ssortingng description; private Ssortingng link; public Item() { setTitle(null); setDescription(null); setLink(null); } public void setTitle(Ssortingng title) { this.title = title; } public Ssortingng getTitle() { return title; } // same as above. } 

Exemple:

 public class Example extends DefaultHandler { private Channel channel; private Items items; private Item item; public Example() { items = new Items(); } public Channel parse(InputStream is) { RootElement root = new RootElement("rss"); Element chanElement = root.getChild("channel"); Element chanTitle = chanElement.getChild("title"); Element chanLink = chanElement.getChild("link"); Element chanDescription = chanElement.getChild("description"); Element chanLastBuildDate = chanElement.getChild("lastBuildDate"); Element chanDocs = chanElement.getChild("docs"); Element chanLanguage = chanElement.getChild("language"); Element chanItem = chanElement.getChild("item"); Element itemTitle = chanItem.getChild("title"); Element itemDescription = chanItem.getChild("description"); Element itemLink = chanItem.getChild("link"); chanElement.setStartElementListener(new StartElementListener() { public void start(Atsortingbutes atsortingbutes) { channel = new Channel(); } }); // Listen for the end of a text element and set the text as our // channel's title. chanTitle.setEndTextElementListener(new EndTextElementListener() { public void end(Ssortingng body) { channel.setTitle(body); } }); // Same thing happens for the other elements of channel ex. // On every  tag occurrence we create a new Item object. chanItem.setStartElementListener(new StartElementListener() { public void start(Atsortingbutes atsortingbutes) { item = new Item(); } }); // On every  tag occurrence we add the current Item object // to the Items container. chanItem.setEndElementListener(new EndElementListener() { public void end() { items.add(item); } }); itemTitle.setEndTextElementListener(new EndTextElementListener() { public void end(Ssortingng body) { item.setTitle(body); } }); // and so on // here we actually parse the InputStream and return the resulting // Channel object. try { Xml.parse(is, Xml.Encoding.UTF_8, root.getContentHandler()); return channel; } catch (SAXException e) { // handle the exception } catch (IOException e) { // handle the exception } return null; } } 

Voici un exemple très rapide, comme vous pouvez le voir. L’avantage majeur de l’utilisation de l’implémentation android.sax SAX est que vous pouvez définir la structure du XML à parsingr, puis simplement append un écouteur d’événement aux éléments appropriés. L’inconvénient est que le code se répète et se gonfle.

Implémentation org.xml.sax

L’ org.xml.sax gestionnaire org.xml.sax SAX est un peu différente.

Ici, vous ne spécifiez pas ou ne déclarez pas votre structure XML, mais écoutez simplement les événements. Les plus utilisés sont les suivants:

  • Début du document
  • Fin du document
  • Element Start
  • Fin d’élément
  • Caractères entre l’élément Start et Element End

Un exemple d’implémentation de gestionnaire utilisant l’object Channel ci-dessus ressemble à ceci.

Exemple

 public class ExampleHandler extends DefaultHandler { private Channel channel; private Items items; private Item item; private boolean inItem = false; private SsortingngBuilder content; public ExampleHandler() { items = new Items(); content = new SsortingngBuilder(); } public void startElement(Ssortingng uri, Ssortingng localName, Ssortingng qName, Atsortingbutes atts) throws SAXException { content = new SsortingngBuilder(); if(localName.equalsIgnoreCase("channel")) { channel = new Channel(); } else if(localName.equalsIgnoreCase("item")) { inItem = true; item = new Item(); } } public void endElement(Ssortingng uri, Ssortingng localName, Ssortingng qName) throws SAXException { if(localName.equalsIgnoreCase("title")) { if(inItem) { item.setTitle(content.toSsortingng()); } else { channel.setTitle(content.toSsortingng()); } } else if(localName.equalsIgnoreCase("link")) { if(inItem) { item.setLink(content.toSsortingng()); } else { channel.setLink(content.toSsortingng()); } } else if(localName.equalsIgnoreCase("description")) { if(inItem) { item.setDescription(content.toSsortingng()); } else { channel.setDescription(content.toSsortingng()); } } else if(localName.equalsIgnoreCase("lastBuildDate")) { channel.setLastBuildDate(content.toSsortingng()); } else if(localName.equalsIgnoreCase("docs")) { channel.setDocs(content.toSsortingng()); } else if(localName.equalsIgnoreCase("language")) { channel.setLanguage(content.toSsortingng()); } else if(localName.equalsIgnoreCase("item")) { inItem = false; items.add(item); } else if(localName.equalsIgnoreCase("channel")) { channel.setItems(items); } } public void characters(char[] ch, int start, int length) throws SAXException { content.append(ch, start, length); } public void endDocument() throws SAXException { // you can do something here for example send // the Channel object somewhere or whatever. } } 

Maintenant, pour être honnête, je ne peux pas vraiment vous dire un réel avantage de cette implémentation de gestionnaire sur celle d’ android.sax . Je peux cependant vous dire l’inconvénient qui devrait être assez évident maintenant. Jetez un coup d’oeil à l’instruction else if dans la méthode startElement . Étant donné que nous avons les balises , le link et la description nous devons les suivre dans la structure XML que nous sums actuellement. C’est-à-dire que si nous rencontrons une départ nous définissons l’indicateur inItem sur true pour nous assurer de mapper les données correctes sur l’object correct et dans la méthode endElement sur false si nous rencontrons une . Pour signaler que nous avons fini avec cette balise item.

Dans cet exemple, il est assez facile de gérer cela, mais avoir à parsingr une structure plus complexe avec des balises répétées à différents niveaux devient difficile. Il vous faudrait soit utiliser Enums, par exemple, pour définir votre état actuel, soit un grand nombre de statuts de switch / case pour vérifier votre position ou une solution plus élégante serait un tracker de balises utilisant une stack de balises.

Dans de nombreux problèmes, il est nécessaire d’utiliser différents types de fichiers XML à des fins différentes. Je n’essaierai pas de saisir l’immensité et de raconter de ma propre expérience ce dont j’avais besoin.

Java, peut-être mon langage de programmation préféré. En outre, cet amour est renforcé par le fait que vous pouvez résoudre n’importe quel problème et trouver un vélo n’est pas nécessaire.

Il m’a donc fallu créer un groupe de clients-serveurs exécutant une firebase database permettant au client de créer des entrées à distance sur le serveur de firebase database. Inutile de vérifier les données d’entrée, etc., etc., mais ce n’est pas à cela.

Comme principe de travail, j’ai choisi, sans hésitation, la transmission d’informations sous forme de fichier xml. Des types suivants:

    3   Ivanov   Ivan   I.   10-03-2005   10-03-2005   10-03-2005   09-06-2009   10-03-2005   1   1   1   2.0   1   

Facilitez la lecture plus loin, sauf pour dire que ce sont les informations sur les institutions médicales. Nom, prénom, identifiant unique, etc. En général, la série de données. Ce fichier a été sécurisé du côté du serveur, puis commence à parsingr le fichier.

Parmi les deux options d’parsing (SAX vs DOM), j’ai choisi la vision de SAX du fait qu’il travaille plus fort, et c’était le premier à tomber entre les mains 🙂

Alors. Comme vous le savez, pour travailler avec l’parsingur, nous devons remplacer les méthodes nécessaires DefaultHandler. Pour commencer, connectez les packages requirejs.

 import org.xml.sax.helpers.DefaultHandler; import org.xml.sax. *; 

Maintenant, nous pouvons commencer à écrire notre parsingur

 public class SAXPars extends DefaultHandler {  ... } 

Commençons par la méthode startDocument (). Comme son nom l’indique, il réagit à un début d’événement du document. Vous pouvez y suspendre diverses actions, telles que l’allocation de mémoire, ou réinitialiser les valeurs, mais notre exemple est assez simple, alors marquez simplement le début du travail d’un message approprié:

 Override public void startDocument () throws SAXException {  System.out.println ("Start parse XML ..."); } 

Prochain. L’parsingur parcourt le document et rencontre l’élément de sa structure. Démarre la méthode startElement (). Et en fait, son apparence ceci: startElement (Ssortingng namespaceURI, Ssortingng localName, Ssortingng qName, Atsortingbuts atts). Ici namespaceURI – l’espace de noms, localName – le nom local de l’élément, qName- une combinaison de nom local avec un espace de noms (séparé par deux points) et atts – les atsortingbuts de cet élément. Dans ce cas, tout simple. Il suffit d’utiliser qName’om et de le lancer dans une ligne de service thisElement. Ainsi, nous marquons l’élément au moment où nous sums.

 @Override public void startElement (Ssortingng namespaceURI, Ssortingng localName, Ssortingng qName, Atsortingbutes atts) throws SAXException {  thisElement = qName; } 

Ensuite, l’object de la réunion, nous en arrivons à sa signification. Ici, inclure des méthodes de caractères (). Il a la forme: caractères (char [] ch, int start, int length). Eh bien ici tout est clair. ch – un fichier contenant la chaîne elle-même dans cet élément. start et length – le numéro de service indiquant le sharepoint départ de la ligne et de la longueur.

 @Override public void characters (char [] ch, int start, int length) throws SAXException {  if (thisElement.equals ("id")) {     doc.setId (new Integer (new Ssortingng (ch, start, length)));  }  if (thisElement.equals ("fam")) {     doc.setFam (new Ssortingng (ch, start, length));  }  if (thisElement.equals ("name")) {     doc.setName (new Ssortingng (ch, start, length));  }  if (thisElement.equals ("otc")) {     doc.setOtc (new Ssortingng (ch, start, length));  }  if (thisElement.equals ("dateb")) {     doc.setDateb (new Ssortingng (ch, start, length));  }  if (thisElement.equals ("datep")) {     doc.setDatep (new Ssortingng (ch, start, length));  }  if (thisElement.equals ("datev")) {     doc.setDatev (new Ssortingng (ch, start, length));  }  if (thisElement.equals ("datebegin")) {     doc.setDatebegin (new Ssortingng (ch, start, length));  }  if (thisElement.equals ("dateend")) {     doc.setDateend (new Ssortingng (ch, start, length));  }  if (thisElement.equals ("vdolid")) {     doc.setVdolid (new Integer (new Ssortingng (ch, start, length)));  }  if (thisElement.equals ("specid")) {     doc.setSpecid (new Integer (new Ssortingng (ch, start, length)));  }  if (thisElement.equals ("klavid")) {     doc.setKlavid (new Integer (new Ssortingng (ch, start, length)));  }  if (thisElement.equals ("stav")) {     doc.setStav (new Float (new Ssortingng (ch, start, length)));  }  if (thisElement.equals ("progid")) {     doc.setProgid (new Integer (new Ssortingng (ch, start, length)));  } } 

Ah oui. J’ai presque oublié. Comme le but de plier les données naparsennye parle au type de médecins. Cette classe est définie et possède tous les déterminants nécessaires.

L’élément évident suivant se termine et il est suivi par le suivant. Responsable de la fin de endElement (). Il nous indique que l’article est terminé et que vous pouvez faire n’importe quoi en ce moment. Va procéder. Nettoyer l’élément.

 @Override public void endElement (Ssortingng namespaceURI, Ssortingng localName, Ssortingng qName) throws SAXException {  thisElement = ""; } 

Venant donc tout le document, nous arrivons à la fin du fichier. Work endDocument (). Dans ce document, nous pouvons libérer de la mémoire, faire des impressions diagnostichesuyu, etc. Dans notre cas, il suffit d’écrire à propos de la fin de l’parsing.

 @Override public void endDocument () {  System.out.println ("Stop parse XML ..."); } 

Nous avons donc une classe pour parsingr xml notre format. Voici le texte intégral:

 import org.xml.sax.helpers.DefaultHandler; import org.xml.sax. *; public class SAXPars extends DefaultHandler { Doctors doc = new Doctors (); Ssortingng thisElement = ""; public Doctors getResult () {  return doc; } @Override public void startDocument () throws SAXException {  System.out.println ("Start parse XML ..."); } @Override public void startElement (Ssortingng namespaceURI, Ssortingng localName, Ssortingng qName, Atsortingbutes atts) throws SAXException {  thisElement = qName; } @Override public void endElement (Ssortingng namespaceURI, Ssortingng localName, Ssortingng qName) throws SAXException {  thisElement = ""; } @Override public void characters (char [] ch, int start, int length) throws SAXException {  if (thisElement.equals ("id")) {     doc.setId (new Integer (new Ssortingng (ch, start, length)));  }  if (thisElement.equals ("fam")) {     doc.setFam (new Ssortingng (ch, start, length));  }  if (thisElement.equals ("name")) {     doc.setName (new Ssortingng (ch, start, length));  }  if (thisElement.equals ("otc")) {     doc.setOtc (new Ssortingng (ch, start, length));  }  if (thisElement.equals ("dateb")) {     doc.setDateb (new Ssortingng (ch, start, length));  }  if (thisElement.equals ("datep")) {     doc.setDatep (new Ssortingng (ch, start, length));  }  if (thisElement.equals ("datev")) {     doc.setDatev (new Ssortingng (ch, start, length));  }  if (thisElement.equals ("datebegin")) {     doc.setDatebegin (new Ssortingng (ch, start, length));  }  if (thisElement.equals ("dateend")) {     doc.setDateend (new Ssortingng (ch, start, length));  }  if (thisElement.equals ("vdolid")) {     doc.setVdolid (new Integer (new Ssortingng (ch, start, length)));  }  if (thisElement.equals ("specid")) {     doc.setSpecid (new Integer (new Ssortingng (ch, start, length)));  }  if (thisElement.equals ("klavid")) {     doc.setKlavid (new Integer (new Ssortingng (ch, start, length)));  }  if (thisElement.equals ("stav")) {     doc.setStav (new Float (new Ssortingng (ch, start, length)));  }  if (thisElement.equals ("progid")) {     doc.setProgid (new Integer (new Ssortingng (ch, start, length)));  } } @Override public void endDocument () {  System.out.println ("Stop parse XML ..."); } } 

J’espère que le sujet a permis de présenter facilement l’essence de l’parsingur SAX.

Ne jugez pas ssortingctement le premier article 🙂 J’espère que c’était au moins quelqu’un d’utile.

UPD: Pour exécuter cet parsingur, vous pouvez utiliser ce code:

 SAXParserFactory factory = SAXParserFactory.newInstance (); SAXParser parser = factory.newSAXParser (); SAXPars saxp = new SAXPars (); parser.parse (new File ("..."), saxp);