Fornirò una risposta generale orientata alle domande e risposte per questa domanda:
Rispondi alle domande
Perché abbiamo bisogno del parser XML?
Abbiamo bisogno del parser XML perché non vogliamo fare tutto da zero nella nostra applicazione e abbiamo bisogno di alcuni programmi o librerie "helper" per fare qualcosa di livello molto basso ma molto necessario per noi. Queste cose di basso livello ma necessarie includono il controllo della correttezza, la convalida del documento rispetto al DTD o allo schema (solo per la convalida dei parser), la risoluzione dei riferimenti ai caratteri, la comprensione delle sezioni CDATA e così via. I parser XML sono programmi "helper" e faranno tutti questi lavori. Con il parser XML, siamo protetti da molte di queste complessità e potremmo concentrarci solo sulla programmazione ad alto livello attraverso le API implementate dai parser, e quindi ottenere efficienza di programmazione.
Qual è il migliore, SAX o DOM?
Sia il parser SAX che DOM hanno i loro vantaggi e svantaggi. Quale è meglio dovrebbe dipendere dalle caratteristiche della tua applicazione (fai riferimento ad alcune domande di seguito).
Quale parser può ottenere una migliore velocità, parser DOM o SAX?
Il parser SAX può ottenere una velocità migliore.
Qual è la differenza tra API basata su albero e API basata su eventi?
Un'API basata su albero è centrata attorno a una struttura ad albero e quindi fornisce interfacce su componenti di un albero (che è un documento DOM) come l'interfaccia Documento, l'interfaccia Nodo, l'interfaccia NodeList, l'interfaccia Element, l'interfaccia Attr e così via. Al contrario, tuttavia, un'API basata su eventi fornisce interfacce sui gestori. Esistono quattro interfacce del gestore, interfaccia ContentHandler, interfaccia DTDHandler, interfaccia EntityResolver e interfaccia ErrorHandler.
Qual è la differenza tra un parser DOM e un parser SAX?
I parser DOM e i parser SAX funzionano in diversi modi:
Un parser DOM crea una struttura ad albero in memoria dal documento di input e quindi attende le richieste dal client. Ma un parser SAX non crea alcuna struttura interna. Invece, prende le occorrenze dei componenti di un documento di input come eventi e dice al client cosa legge mentre legge il documento di input. UN
Il parser DOM serve sempre l'applicazione client con l'intero documento, indipendentemente dalla quantità effettivamente richiesta dal client. Ma un parser SAX serve l'applicazione client sempre solo con pezzi del documento in un dato momento.
- Con il parser DOM, le chiamate di metodo nell'applicazione client devono essere esplicite e formano un tipo di catena. Ma con SAX, alcuni determinati metodi (di solito sostituiti dal cient) verranno invocati automaticamente (implicitamente) in un modo che viene chiamato "callback" quando si verificano determinati eventi. Questi metodi non devono essere chiamati esplicitamente dal client, sebbene potremmo chiamarli in modo esplicito.
Come decidiamo quale parser è buono?
Idealmente un buon parser dovrebbe essere veloce (efficiente in termini di tempo), efficiente in termini di spazio, ricco di funzionalità e facile da usare. Ma in realtà, nessuno dei principali parser ha tutte queste caratteristiche allo stesso tempo. Ad esempio, un parser DOM è ricco di funzionalità (perché crea un albero DOM in memoria e consente di accedere ripetutamente a qualsiasi parte del documento e consente di modificare l'albero DOM), ma è inefficiente nello spazio quando il documento è enorme e ci vuole un po 'di tempo per imparare a lavorarci. Un parser SAX, tuttavia, è molto più efficiente in termini di spazio in caso di documenti di input di grandi dimensioni (perché non crea alcuna struttura interna). Inoltre, funziona più velocemente ed è più facile da imparare rispetto al DOM Parser perché la sua API è davvero semplice. Ma dal punto di vista della funzionalità, fornisce meno funzioni, il che significa che gli stessi utenti devono occuparsi di più, come la creazione di proprie strutture dati. A proposito, cos'è un buon parser? Penso che la risposta dipenda davvero dalle caratteristiche della tua applicazione.
Quali sono alcune applicazioni del mondo reale in cui l'utilizzo del parser SAX è vantaggioso rispetto all'utilizzo del parser DOM e viceversa? Quali sono le solite applicazioni per un parser DOM e per un parser SAX?
Nei seguenti casi, l'utilizzo del parser SAX è vantaggioso rispetto all'utilizzo del parser DOM.
- Il documento di input è troppo grande per la memoria disponibile (in realtà in questo caso SAX è l'unica scelta)
- È possibile elaborare il documento in piccoli blocchi contigui di input. Non è necessario l'intero documento prima di poter svolgere un lavoro utile
- Vuoi solo usare il parser per estrarre le informazioni di interesse e tutto il tuo calcolo sarà completamente basato sulle strutture di dati create da te. In realtà nella maggior parte delle nostre applicazioni, creiamo strutture di dati nostre che di solito non sono così complicate come l'albero del DOM. Da questo senso, penso, la possibilità di usare un parser DOM è inferiore a quella di usare un parser SAX.
Nei seguenti casi, l'utilizzo del parser DOM è vantaggioso rispetto all'utilizzo del parser SAX.
- L'applicazione deve accedere contemporaneamente a parti del documento ampiamente separate.
- La tua applicazione potrebbe probabilmente utilizzare una struttura di dati interna che è quasi complicata come il documento stesso.
- L'applicazione deve modificare il documento ripetutamente.
- L'applicazione deve archiviare il documento per un periodo di tempo significativo attraverso numerose chiamate di metodo.
Esempio (utilizzare un parser DOM o un parser SAX?):
Supponiamo che un istruttore abbia un documento XML contenente tutte le informazioni personali degli studenti, nonché i punti che i suoi studenti hanno fatto nella sua classe, e ora sta assegnando i voti finali per gli studenti usando un'applicazione. Quello che vuole produrre è un elenco con il SSN e i voti. Inoltre supponiamo che nella sua domanda, l'istruttore non utilizzi alcuna struttura di dati come array per memorizzare le informazioni personali degli studenti e i punti. Se l'istruttore decide di assegnare A a coloro che hanno guadagnato la classe media o superiore e di dare B agli altri, allora è meglio usare un parser DOM nella sua applicazione. Il motivo è che non ha modo di sapere quanto è la media della classe prima che l'intero documento venga elaborato. Quello che probabilmente deve fare nella sua domanda, è prima di tutto esaminare tutti gli studenti punti e calcolare la media, quindi rivedere il documento e assegnare il voto finale a ciascuno studente confrontando i punti guadagnati con la media della classe. Se, tuttavia, l'istruttore adotta una politica di classificazione tale che agli studenti che hanno ottenuto 90 punti o più, vengano assegnati A e agli altri vengano assegnati B, allora probabilmente sarebbe meglio usare un parser SAX. Il motivo è che, per assegnare a ogni studente un voto finale, non è necessario attendere l'elaborazione dell'intero documento. Poteva assegnare immediatamente un voto a uno studente una volta che il parser SAX ha letto il voto di questo studente. Nell'analisi sopra, abbiamo ipotizzato che l'istruttore non abbia creato una propria struttura di dati. E se crea la propria struttura di dati, come una matrice di stringhe per memorizzare il SSN e una matrice di numeri interi per conservare i punti? In questo caso, Penso che SAX sia una scelta migliore, prima che questo possa risparmiare sia memoria che tempo, ma portare a termine il lavoro. Bene, un'altra considerazione su questo esempio. Cosa succede se ciò che l'istruttore vuole fare non è stampare un elenco, ma salvare il documento originale con il voto di ogni studente aggiornato? In questo caso, un parser DOM dovrebbe essere una scelta migliore, indipendentemente dalla politica di classificazione che sta adottando. Non ha bisogno di creare una propria struttura di dati. Quello che deve fare è prima modificare l'albero DOM (ovvero, impostare il valore sul nodo 'grade') e quindi salvare l'intero albero modificato. Se sceglie di utilizzare un parser SAX anziché un parser DOM, in questo caso deve creare una struttura di dati che è quasi complicata come un albero DOM prima di poter eseguire il lavoro. ma fai il lavoro. Bene, un'altra considerazione su questo esempio. Cosa succede se ciò che l'istruttore vuole fare non è stampare un elenco, ma salvare il documento originale con il voto di ogni studente aggiornato? In questo caso, un parser DOM dovrebbe essere una scelta migliore, indipendentemente dalla politica di classificazione che sta adottando. Non ha bisogno di creare una propria struttura di dati. Quello che deve fare è prima modificare l'albero DOM (ovvero, impostare il valore sul nodo 'grade') e quindi salvare l'intero albero modificato. Se sceglie di utilizzare un parser SAX anziché un parser DOM, in questo caso deve creare una struttura di dati che è quasi complicata come un albero DOM prima di poter eseguire il lavoro. ma fai il lavoro. Bene, un'altra considerazione su questo esempio. Cosa succede se ciò che l'istruttore vuole fare non è stampare un elenco, ma salvare il documento originale con il voto di ogni studente aggiornato? In questo caso, un parser DOM dovrebbe essere una scelta migliore, indipendentemente dalla politica di classificazione che sta adottando. Non ha bisogno di creare una propria struttura di dati. Quello che deve fare è prima modificare l'albero DOM (ovvero, impostare il valore sul nodo 'grade') e quindi salvare l'intero albero modificato. Se sceglie di utilizzare un parser SAX anziché un parser DOM, in questo caso deve creare una struttura di dati che è quasi complicata come un albero DOM prima di poter eseguire il lavoro. ma per salvare il documento originale con il voto di ogni studente aggiornato? In questo caso, un parser DOM dovrebbe essere una scelta migliore, indipendentemente dalla politica di classificazione che sta adottando. Non ha bisogno di creare una propria struttura di dati. Quello che deve fare è prima modificare l'albero DOM (ovvero, impostare il valore sul nodo 'grade') e quindi salvare l'intero albero modificato. Se sceglie di utilizzare un parser SAX anziché un parser DOM, in questo caso deve creare una struttura di dati che è quasi complicata come un albero DOM prima di poter eseguire il lavoro. ma per salvare il documento originale con il voto di ogni studente aggiornato? In questo caso, un parser DOM dovrebbe essere una scelta migliore, indipendentemente dalla politica di classificazione che sta adottando. Non ha bisogno di creare una propria struttura di dati. Quello che deve fare è prima modificare l'albero DOM (ovvero, impostare il valore sul nodo 'grade') e quindi salvare l'intero albero modificato. Se sceglie di utilizzare un parser SAX anziché un parser DOM, in questo caso deve creare una struttura di dati che è quasi complicata come un albero DOM prima di poter eseguire il lavoro. nodo) e quindi salvare l'intero albero modificato. Se sceglie di utilizzare un parser SAX anziché un parser DOM, in questo caso deve creare una struttura di dati che è quasi complicata come un albero DOM prima di poter eseguire il lavoro. nodo) e quindi salvare l'intero albero modificato. Se sceglie di utilizzare un parser SAX anziché un parser DOM, in questo caso deve creare una struttura di dati che è quasi complicata come un albero DOM prima di poter eseguire il lavoro.
Un esempio
Dichiarazione del problema : scrivere un programma Java per estrarre tutte le informazioni sui cerchi che sono elementi in un determinato documento XML. Partiamo dal presupposto che ogni elemento del cerchio ha tre elementi figlio (cioè, x, y e raggio) oltre a un attributo di colore. Di seguito è riportato un documento di esempio:
<?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>
Programma con 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);}
}
}
Programma con 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);
}
}
}