Je vais fournir une réponse générale orientée Q & A pour cette question:
Réponse aux questions
Pourquoi avons-nous besoin d'un analyseur XML?
Nous avons besoin de l'analyseur XML parce que nous ne voulons pas tout faire dans notre application à partir de zéro, et nous avons besoin de quelques programmes ou bibliothèques "d'aide" pour faire quelque chose de très bas niveau mais très nécessaire pour nous. Ces choses de bas niveau mais nécessaires comprennent la vérification de la bonne forme, la validation du document par rapport à sa DTD ou son schéma (juste pour valider les analyseurs), la résolution de la référence de caractère, la compréhension des sections CDATA, etc. Les analyseurs XML ne sont que de tels programmes "auxiliaires" et ils feront tous ces travaux. Avec l'analyseur XML, nous sommes protégés de beaucoup de ces complexités et nous pourrions nous concentrer uniquement sur la programmation de haut niveau grâce aux API implémentées par les analyseurs, et ainsi gagner en efficacité de programmation.
Lequel est le meilleur, SAX ou DOM?
Les analyseurs SAX et DOM ont leurs avantages et leurs inconvénients. Laquelle est la meilleure devrait dépendre des caractéristiques de votre application (veuillez vous référer aux questions ci-dessous).
Quel analyseur peut obtenir une meilleure vitesse, analyseurs DOM ou SAX?
L'analyseur SAX peut obtenir une meilleure vitesse.
Quelle est la différence entre une API basée sur un arbre et une API basée sur un événement?
Une API basée sur l'arborescence est centrée sur une structure arborescente et fournit donc des interfaces sur les composants d'une arborescence (qui est un document DOM) tels que l'interface Document, l'interface Node, l'interface NodeList, l'interface Element, l'interface Attr, etc. En revanche, cependant, une API basée sur les événements fournit des interfaces sur les gestionnaires. Il existe quatre interfaces de gestionnaire, l'interface ContentHandler, l'interface DTDHandler, l'interface EntityResolver et l'interface ErrorHandler.
Quelle est la différence entre un analyseur DOM et un analyseur SAX?
Les analyseurs DOM et SAX fonctionnent de différentes manières:
Un analyseur DOM crée une arborescence en mémoire à partir du document d'entrée, puis attend les demandes du client. Mais un analyseur SAX ne crée aucune structure interne. Au lieu de cela, il prend les occurrences des composants d'un document d'entrée en tant qu'événements et indique au client ce qu'il lit lorsqu'il lit le document d'entrée. UNE
L'analyseur DOM sert toujours l'application cliente avec tout le document, quel que soit le montant réellement requis par le client. Mais un analyseur SAX sert l'application client toujours uniquement avec des morceaux du document à un moment donné.
- Avec l'analyseur DOM, les appels de méthode dans l'application client doivent être explicites et forment une sorte de chaîne. Mais avec SAX, certaines méthodes (généralement remplacées par le client) seront invoquées automatiquement (implicitement) d'une manière qui est appelée "rappel" lorsque certains événements se produisent. Ces méthodes ne doivent pas être appelées explicitement par le client, bien que nous puissions les appeler explicitement.
Comment décidons-nous quel analyseur est bon?
Idéalement, un bon analyseur doit être rapide (gain de temps), peu encombrant, riche en fonctionnalités et facile à utiliser. Mais en réalité, aucun des principaux analyseurs n'a toutes ces fonctionnalités en même temps. Par exemple, un analyseur DOM est riche en fonctionnalités (car il crée une arborescence DOM en mémoire et vous permet d'accéder à n'importe quelle partie du document à plusieurs reprises et vous permet de modifier l'arborescence DOM), mais son espace est inefficace lorsque le document est énorme , et cela prend un peu de temps pour apprendre à travailler avec. Un analyseur SAX, cependant, est beaucoup plus efficace en cas de gros document d'entrée (car il ne crée aucune structure interne). De plus, il s'exécute plus rapidement et est plus facile à apprendre que DOM Parser car son API est vraiment simple. Mais du point de vue de la fonctionnalité, il offre moins de fonctions, ce qui signifie que les utilisateurs eux-mêmes doivent en prendre plus en charge, comme la création de leurs propres structures de données. Au fait, qu'est-ce qu'un bon analyseur? Je pense que la réponse dépend vraiment des caractéristiques de votre application.
Quelles sont les applications du monde réel où l'utilisation de l'analyseur SAX est avantageuse par rapport à l'utilisation de l'analyseur DOM et vice versa? Quelles sont les applications habituelles pour un analyseur DOM et pour un analyseur SAX?
Dans les cas suivants, l'utilisation de l'analyseur SAX est avantageuse par rapport à l'utilisation de l'analyseur DOM.
- Le document d'entrée est trop volumineux pour la mémoire disponible (en fait dans ce cas, SAX est votre seul choix)
- Vous pouvez traiter le document en petits morceaux contigus d'entrée. Vous n'avez pas besoin de l'intégralité du document avant de pouvoir effectuer un travail utile
- Vous souhaitez simplement utiliser l'analyseur pour extraire les informations d'intérêt, et tout votre calcul sera entièrement basé sur les structures de données créées par vous-même. En fait, dans la plupart de nos applications, nous créons nos propres structures de données qui ne sont généralement pas aussi compliquées que l'arborescence DOM. De ce point de vue, je pense que la possibilité d'utiliser un analyseur DOM est inférieure à celle d'utiliser un analyseur SAX.
Dans les cas suivants, l'utilisation de l'analyseur DOM est avantageuse par rapport à l'utilisation de l'analyseur SAX.
- Votre application doit accéder simultanément à des parties du document largement séparées.
- Votre application peut probablement utiliser une structure de données interne qui est presque aussi compliquée que le document lui-même.
- Votre application doit modifier le document à plusieurs reprises.
- Votre application doit stocker le document pendant une durée significative via de nombreux appels de méthode.
Exemple (utiliser un analyseur DOM ou un analyseur SAX?):
Supposons qu'un instructeur dispose d'un document XML contenant toutes les informations personnelles des élèves ainsi que les points soulevés par ses élèves dans sa classe, et il attribue maintenant des notes finales aux élèves à l'aide d'une application. Ce qu'il veut produire, c'est une liste avec le SSN et les grades. Nous supposons également que dans son application, l'instructeur n'utilise aucune structure de données telle que des tableaux pour stocker les informations personnelles de l'étudiant et les points. Si l'instructeur décide de donner des A à ceux qui ont obtenu la moyenne de la classe ou plus, et de donner des B aux autres, alors il vaut mieux utiliser un analyseur DOM dans sa demande. La raison en est qu'il n'a aucun moyen de connaître la moyenne de la classe avant que le document entier ne soit traité. Ce qu'il doit probablement faire dans sa candidature, c'est d'abord regarder à travers tous les points et calculer la moyenne, puis parcourez à nouveau le document et attribuez la note finale à chaque élève en comparant les points qu'il a gagnés à la moyenne de la classe. Si, cependant, l'instructeur adopte une telle politique de notation que les étudiants qui ont obtenu 90 points ou plus, se voient attribuer des A et les autres des B, alors il vaut probablement mieux utiliser un analyseur SAX. La raison en est que pour attribuer une note finale à chaque étudiant, il n'a pas besoin d'attendre que l'intégralité du document soit traité. Il pourrait immédiatement attribuer une note à un étudiant une fois que l'analyseur SAX aura lu la note de cet étudiant. Dans l'analyse ci-dessus, nous avons supposé que l'instructeur n'avait créé aucune structure de données propre. Et s'il crée sa propre structure de données, comme un tableau de chaînes pour stocker le SSN et un tableau d'entiers pour stocker les points? Dans ce cas, Je pense que SAX est un meilleur choix, avant que cela ne puisse également économiser de la mémoire et du temps, tout en faisant le travail. Eh bien, encore une considération sur cet exemple. Que faire si l'instructeur ne veut pas imprimer une liste, mais sauvegarder le document original avec la note de chaque élève mise à jour? Dans ce cas, un analyseur DOM devrait être un meilleur choix, quelle que soit la politique de notation qu'il adopte. Il n'a pas besoin de créer sa propre structure de données. Ce qu'il doit faire, c'est d'abord modifier l'arborescence DOM (c'est-à-dire définir la valeur du nœud «grade»), puis enregistrer l'intégralité de l'arborescence modifiée. S'il choisit d'utiliser un analyseur SAX au lieu d'un analyseur DOM, alors dans ce cas, il doit créer une structure de données qui est presque aussi compliquée qu'un arbre DOM avant de pouvoir faire le travail. encore faire le travail. Eh bien, encore une considération sur cet exemple. Que faire si l'instructeur ne veut pas imprimer une liste, mais sauvegarder le document original avec la note de chaque élève mise à jour? Dans ce cas, un analyseur DOM devrait être un meilleur choix, quelle que soit la politique de notation qu'il adopte. Il n'a pas besoin de créer sa propre structure de données. Ce qu'il doit faire, c'est d'abord modifier l'arborescence DOM (c'est-à-dire définir la valeur du nœud «grade»), puis enregistrer l'intégralité de l'arbre modifié. S'il choisit d'utiliser un analyseur SAX au lieu d'un analyseur DOM, alors dans ce cas, il doit créer une structure de données qui est presque aussi compliquée qu'un arbre DOM avant de pouvoir faire le travail. encore faire le travail. Eh bien, encore une considération sur cet exemple. Que faire si l'instructeur ne veut pas imprimer une liste, mais sauvegarder le document original avec la note de chaque élève mise à jour? Dans ce cas, un analyseur DOM devrait être un meilleur choix, quelle que soit la politique de notation qu'il adopte. Il n'a pas besoin de créer sa propre structure de données. Ce qu'il doit faire, c'est d'abord modifier l'arborescence DOM (c'est-à-dire définir la valeur du nœud «grade»), puis enregistrer l'intégralité de l'arborescence modifiée. S'il choisit d'utiliser un analyseur SAX au lieu d'un analyseur DOM, alors dans ce cas, il doit créer une structure de données qui est presque aussi compliquée qu'un arbre DOM avant de pouvoir faire le travail. mais pour sauvegarder le document original avec la note de chaque élève mise à jour? Dans ce cas, un analyseur DOM devrait être un meilleur choix, quelle que soit la politique de notation qu'il adopte. Il n'a pas besoin de créer sa propre structure de données. Ce qu'il doit faire, c'est d'abord modifier l'arborescence DOM (c'est-à-dire définir la valeur du nœud «grade»), puis enregistrer l'intégralité de l'arborescence modifiée. S'il choisit d'utiliser un analyseur SAX au lieu d'un analyseur DOM, alors dans ce cas, il doit créer une structure de données qui est presque aussi compliquée qu'un arbre DOM avant de pouvoir faire le travail. mais pour sauvegarder le document original avec la note de chaque élève mise à jour? Dans ce cas, un analyseur DOM devrait être un meilleur choix, quelle que soit la politique de notation qu'il adopte. Il n'a pas besoin de créer sa propre structure de données. Ce qu'il doit faire, c'est d'abord modifier l'arborescence DOM (c'est-à-dire définir la valeur du nœud «grade»), puis enregistrer l'intégralité de l'arborescence modifiée. S'il choisit d'utiliser un analyseur SAX au lieu d'un analyseur DOM, alors dans ce cas, il doit créer une structure de données qui est presque aussi compliquée qu'un arbre DOM avant de pouvoir faire le travail. nœud), puis enregistrez l'arborescence entièrement modifiée. S'il choisit d'utiliser un analyseur SAX au lieu d'un analyseur DOM, alors dans ce cas, il doit créer une structure de données qui est presque aussi compliquée qu'un arbre DOM avant de pouvoir faire le travail. nœud), puis enregistrez l'arborescence entièrement modifiée. S'il choisit d'utiliser un analyseur SAX au lieu d'un analyseur DOM, alors dans ce cas, il doit créer une structure de données qui est presque aussi compliquée qu'un arbre DOM avant de pouvoir faire le travail.
Un exemple
Énoncé du problème : Écrivez un programme Java pour extraire toutes les informations sur les cercles qui sont des éléments dans un document XML donné. Nous supposons que chaque élément de cercle a trois éléments enfants (c'est-à-dire, x, y et rayon) ainsi qu'un attribut de couleur. Un exemple de document est donné ci-dessous:
<?xml version="1.0"?>
<!DOCTYPE shapes [
<!ELEMENT shapes (circle)*>
<!ELEMENT circle (x,y,radius)>
<!ELEMENT x (#PCDATA)>
<!ELEMENT y (#PCDATA)>
<!ELEMENT radius (#PCDATA)>
<!ATTLIST circle color CDATA #IMPLIED>
]>
<shapes>
<circle color="BLUE">
<x>20</x>
<y>20</y>
<radius>20</radius>
</circle>
<circle color="RED" >
<x>40</x>
<y>40</y>
<radius>20</radius>
</circle>
</shapes>
Programmer avec DOMparser
import java.io.*;
import org.w3c.dom.*;
import org.apache.xerces.parsers.DOMParser;
public class shapes_DOM {
static int numberOfCircles = 0; // total number of circles seen
static int x[] = new int[1000]; // X-coordinates of the centers
static int y[] = new int[1000]; // Y-coordinates of the centers
static int r[] = new int[1000]; // radius of the circle
static String color[] = new String[1000]; // colors of the circles
public static void main(String[] args) {
try{
// create a DOMParser
DOMParser parser=new DOMParser();
parser.parse(args[0]);
// get the DOM Document object
Document doc=parser.getDocument();
// get all the circle nodes
NodeList nodelist = doc.getElementsByTagName("circle");
numberOfCircles = nodelist.getLength();
// retrieve all info about the circles
for(int i=0; i<nodelist.getLength(); i++) {
// get one circle node
Node node = nodelist.item(i);
// get the color attribute
NamedNodeMap attrs = node.getAttributes();
if(attrs.getLength() > 0)
color[i]=(String)attrs.getNamedItem("color").getNodeValue();
// get the child nodes of a circle node
NodeList childnodelist = node.getChildNodes();
// get the x and y value
for(int j=0; j<childnodelist.getLength(); j++) {
Node childnode = childnodelist.item(j);
Node textnode = childnode.getFirstChild();//the only text node
String childnodename=childnode.getNodeName();
if(childnodename.equals("x"))
x[i]= Integer.parseInt(textnode.getNodeValue().trim());
else if(childnodename.equals("y"))
y[i]= Integer.parseInt(textnode.getNodeValue().trim());
else if(childnodename.equals("radius"))
r[i]= Integer.parseInt(textnode.getNodeValue().trim());
}
}
// print the result
System.out.println("circles="+numberOfCircles);
for(int i=0;i<numberOfCircles;i++) {
String line="";
line=line+"(x="+x[i]+",y="+y[i]+",r="+r[i]+",color="+color[i]+")";
System.out.println(line);
}
} catch (Exception e) {e.printStackTrace(System.err);}
}
}
Programme avec SAXparser
import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;
public class shapes_SAX extends DefaultHandler {
static int numberOfCircles = 0; // total number of circles seen
static int x[] = new int[1000]; // X-coordinates of the centers
static int y[] = new int[1000]; // Y-coordinates of the centers
static int r[] = new int[1000]; // radius of the circle
static String color[] = new String[1000]; // colors of the circles
static int flagX=0; //to remember what element has occurred
static int flagY=0; //to remember what element has occurred
static int flagR=0; //to remember what element has occurred
// main method
public static void main(String[] args) {
try{
shapes_SAX SAXHandler = new shapes_SAX (); // an instance of this class
SAXParser parser=new SAXParser(); // create a SAXParser object
parser.setContentHandler(SAXHandler); // register with the ContentHandler
parser.parse(args[0]);
} catch (Exception e) {e.printStackTrace(System.err);} // catch exeptions
}
// override the startElement() method
public void startElement(String uri, String localName,
String rawName, Attributes attributes) {
if(rawName.equals("circle")) // if a circle element is seen
color[numberOfCircles]=attributes.getValue("color"); // get the color attribute
else if(rawName.equals("x")) // if a x element is seen set the flag as 1
flagX=1;
else if(rawName.equals("y")) // if a y element is seen set the flag as 2
flagY=1;
else if(rawName.equals("radius")) // if a radius element is seen set the flag as 3
flagR=1;
}
// override the endElement() method
public void endElement(String uri, String localName, String rawName) {
// in this example we do not need to do anything else here
if(rawName.equals("circle")) // if a circle element is ended
numberOfCircles += 1; // increment the counter
}
// override the characters() method
public void characters(char characters[], int start, int length) {
String characterData =
(new String(characters,start,length)).trim(); // get the text
if(flagX==1) { // indicate this text is for <x> element
x[numberOfCircles] = Integer.parseInt(characterData);
flagX=0;
}
else if(flagY==1) { // indicate this text is for <y> element
y[numberOfCircles] = Integer.parseInt(characterData);
flagY=0;
}
else if(flagR==1) { // indicate this text is for <radius> element
r[numberOfCircles] = Integer.parseInt(characterData);
flagR=0;
}
}
// override the endDocument() method
public void endDocument() {
// when the end of document is seen, just print the circle info
System.out.println("circles="+numberOfCircles);
for(int i=0;i<numberOfCircles;i++) {
String line="";
line=line+"(x="+x[i]+",y="+y[i]+",r="+r[i]+",color="+color[i]+")";
System.out.println(line);
}
}
}